我正在尝试使用(我认为是这样)一家工厂,该工厂根据传递给该方法的枚举创建一个存储库。看起来像这样:

仓库工厂

public class RepositoryFactory
{
    public IRepository<IEntity> GetRepository(FormTypes formType)
    {
        // Represents the IRepository that should be created, based on the form type passed
        var typeToCreate = formType.GetAttribute<EnumTypeAttribute>().Type;

        // return an instance of the form type repository
        IRepository<IEntity> type = Activator.CreateInstance(typeToCreate) as IRepository<IEntity>;

        if (type != null)
            return type;

        throw new ArgumentException(string.Format("No repository found for {0}", nameof(formType)));
    }
}

信息库
public interface IRepository <T>
    where T : class, IEntity
{
    bool Create(IEnumerable<T> entities);

    IEnumerable<T> Read();

    bool Update(IEnumerable<T> entities);

    bool Delete(IEnumerable<T> entities);
}

表格类型
public enum FormTypes
{
    [EnumType(typeof(Form64_9C2Repository))]
    Form64_9C2,

    [EnumType(typeof(Form64_9BaseRepository))]
    Form64_9Base
}

EnumExtensions
public static class EnumExtensions
{

    /// <summary>
    /// Get the Enum attribute
    /// </summary>
    /// <typeparam name="T">The attribute</typeparam>
    /// <param name="enumValue">The enum</param>
    /// <returns>The type to create</returns>
    public static T GetAttribute<T>(this System.Enum enumValue)
        where T : Attribute
    {
        FieldInfo field = enumValue.GetType().GetField(enumValue.ToString());
        object[] attribs = field.GetCustomAttributes(typeof(T), false);
        T result = default(T);

        if (attribs.Length > 0)
        {
            result = attribs[0] as T;
        }

        return result;
    }

}

Form64_9C2储存库
public class Form64_9C2Repository : IRepository<Form64_9C2>
{
    public bool Create(IEnumerable<Form64_9C2> entities)
    {
        throw new NotImplementedException();
    }

    public bool Delete(IEnumerable<Form64_9C2> entities)
    {
        throw new NotImplementedException();
    }

    public IEnumerable<Form64_9C2> Read()
    {
        throw new NotImplementedException();
    }

    public bool Update(IEnumerable<Form64_9C2> entities)
    {
        throw new NotImplementedException();
    }
}

实体
public interface IEntity { }

Form64_9C2( stub )
public class Form64_9C2 : IEntity { }

全部称呼为:
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Repository Factory Example \n\n");

        Business.Factory.RepositoryFactory factory = new Business.Factory.RepositoryFactory();

        // Get a 64 9C2 repository
        var repo9c2 = factory.GetRepository(FormTypes.Form64_9C2);
        Console.WriteLine(repo9c2);
    }
}

我的问题是我的type始终解析为null。我期望得到一个NotImplementedException,但是由于没有有效的formType而得到了ArgumentException

c# - 具有通用存储库的Activator.CreateInstance-LMLPHP

在实现IRepository<T>之前,我的type/repository已成功创建(工作代码here),有什么想法吗?我只是刚刚开始尝试使用工厂,泛型之类的东西,因此,如果我做错了什么,请提出建议!

最佳答案

您的代码由于完全无法编译此行的原因而无法正常工作:

IRepository<IEntity> repo = new Form64_9C2Repository();

即使IRepository<IEntity>实现IRepository<Form64_9C2>,基本上Form64_9C2IEntity也不相同。

如果T接口(interface)上的IRepository通用参数是 covariant ,则可能会起作用:
public interface IRepository<out T> where T : class, IEntity
{
    IEnumerable<T> Read();
}

但是不幸的是,这意味着它只能作为方法的返回类型出现,而不能作为参数出现。对于UpdateDeleteCreate方法,这是不行的。您当然可以定义这样的结构:
public interface IReadonlyRepository<out T> where T : class, IEntity
{
    IEnumerable<T> Read();
}

public interface IRepository<T>: IReadonlyRepository<T> where T : class, IEntity
{
    bool Update(IEnumerable<T> entities);
    bool Delete(IEnumerable<T> entities);
    bool Create(IEnumerable<T> entities);
}

并让您的GetRepository方法返回IReadonlyRepository<IEntity>

如果这对您不起作用,您将需要一个附加参数来指定具体实体类型,以便执行正确的转换:
    public IRepository<TEntity> GetRepository<TEntity>(FormTypes formType) where TEntity: class, IEntity
    {
        // Represents the IRepository that should be created, based on the form type passed
        var typeToCreate = formType.GetAttribute<EnumTypeAttribute>().Type;

        // return an instance of the form type repository
        IRepository<TEntity> type = Activator.CreateInstance(typeToCreate) as IRepository<TEntity>;

        if (type != null)
            return type;

        throw new ArgumentException(string.Format("No repository found for {0}", nameof(formType)));
    }
}

并且在调用时除了指定存储库类型外,您还需要指定实体类型:
var repo9c2 = factory.GetRepository<Form64_9C2>(FormTypes.Form64_9C2);

关于c# - 具有通用存储库的Activator.CreateInstance,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34596035/

10-11 20:50