簡體   English   中英

具有通用存儲庫的Activator.CreateInstance

[英]Activator.CreateInstance with a generic repository

我正在嘗試使用(我認為是)工廠,該工廠根據傳遞給方法的枚舉創建存儲庫。 看起來像這樣:

倉庫工廠

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(存根)

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

在此處輸入圖片說明

在實現IRepository<T>之前,我的type / repository已成功創建( 此處為工作代碼),有什么想法嗎? 我只是剛剛開始嘗試使用工廠,泛型之類的東西-因此,如果我做錯了什么,請告知!

您的代碼由於完全無法編譯此行的原因而無法正常工作:

IRepository<IEntity> repo = new Form64_9C2Repository();

基本上IRepository<IEntity>是不一樣的IRepository<Form64_9C2>即使Form64_9C2器具IEntity

如果IRepository接口上的T泛型參數是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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM