代码之家  ›  专栏  ›  技术社区  ›  Alex

C#泛型和抽象工厂模式-或者类似的方法

  •  2
  • Alex  · 技术社区  · 14 年前

    我正在尝试为我的应用程序编写一种可扩展的数据层,其中一个“存储库”是我的抽象存储类的内存实现

    public abstract class Store<TEntity, TIdentifier> : IStore<TEntity, TIdentifier>
            where TEntity : StorableEntity<TIdentifier>        
    {
      //abstract methods here
    
      public abstract TIdentifier GetUniqueIdentifier();
    }
    

    public abstract class StorableEntity<TIdentifier>
    {
        public TIdentifier ID { get; set; }
    }
    

    我有一个名为“InMemoryStore”的具体存储类,它看起来像这样:

    public class InMemoryStore<T, U> : Store<T, U>
        where T : StorableEntity<U>
    {
        protected static Dictionary<U, T> store = new Dictionary<U, T>();
    
        public override U GetUniqueIdentifier()
        {
        // call relevant "generator" here - SOMETHING LIKE THIS??
        // var generator = GetGeneratorSomehow(U);
        // return generator.Create();
        }
    }
    

    现在,“U”的类型可以是string,int,Guid等等。。。 (大多数情况下可能是int)

    public interface IUIDGenerator<T>
    {
        T Create(ICollection<T> collection);
    }
    

    在上面的“InMemoryStore”中,我将创建一个IUIDGenerator实例,传入storedictionarys键集合,并调用“create”方法来返回所需类型的唯一标识符。

    例如,我可以有一个这样的IntUIDGenerator类(它将作为一种增量数字生成器,基于字典键中已有的数字)

    public class IntUIDGenerator : IUIDGenerator<int>
    {
        public int Create(ICollection<int> collection)
        {
            var result = collection.Max() + 1;
            if (collection.Contains(result))
                return result;
    
            throw new NotUniqueException();
        }
    }
    

    我需要做的是,在InMemoryStore中,识别U的类型(标识符的类型),并能够动态地选择所需的IUIDGenerator的具体实现—我如何做到这一点?

    我考虑过使用一种类工厂模式——将所有可用的uidgeGenerator加载到字典中。。。但它们可以有不同的类型?

    另外,我知道我的问题的标题可能有点离题-如果有人有更好的建议,请随时评论,我会改变它。

    4 回复  |  直到 14 年前
        1
  •  2
  •   djdd87    14 年前

    您可以使用IoC框架,例如 Unity ,城堡, Ninject ,然后您可以使用以下内容配置容器:

    _container = new UnityContainer();
    _container.RegisterType<IUIDGenerator<int>, IntUIDGenerator);
    _container.RegisterType<IUIDGenerator<Guid>, GuidUIDGenerator);
    

    那么在你的课堂上,你有如下的东西:

    public override U GetUniqueIdentifier()
    {
        var generator = _container.Resolve<IUIDGenerator<U>>();
        return generator.Create();
    }
    
        2
  •  0
  •   MartinStettner    14 年前

    我想你至少得用一个石膏。如果你把所有的发电机都存储在地图上

    Map<Type, object> generators;
    

    你可以用

    class InMemoryStore<T,U> {
      public override U GetUniqueIdentifier() {
        var generator = generators[typeof(U)] as IUIDGenerator<U>;
        return generator.Create(collection);
      }
    }
    

    当然,我省略了所有类型的验证代码:)(比如检查 U 在地图上等等…)

        3
  •  0
  •   sisve    14 年前

    简而言之:使用 dependency injection ,并让DI容器为您处理它。

        4
  •  0
  •   Mark H    14 年前

    public class InMemoryStore<T, U, V> : Store<T, U>
        where T : StorableEntity<U>
        where V : IUIDGenerator<U>, new() {
    
        public override U GetUniqueIdentifier()
        {
            return (V)(Activator.CreateInstance<V>()).Create();
        }
    }