2016-01-04 14 views
5

私は、(私の考えでは)メソッドに渡される列挙型に応じてリポジトリを作成するファクトリを使いこなしています。次のようになります。Activator.CreateInstanceと汎用リポジトリ

RepositoryFactory

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))); 
    } 
} 

IRepository

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); 
} 

FormTypes

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; 
    } 

} 

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); 
    } 
} 

私の問題:としてそれをすべてを呼び出す

Form64_9C2Repository

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(); 
    } 
} 

IEntity

public interface IEntity { } 

Form64_9C2(スタブ)

public class Form64_9C2 : IEntity { } 

私のtypeは常にnullに解決されています。私はNotImplementedExceptionを得ることを期待していますが、代わりにArgumentExceptionが有効なformTypeを持っていないために取得しています。

enter image description here

IRepository<T>type/repositoryを実装する前に成功(コードhere作業)が作成されていた、任意のアイデア?私はちょうど工場、ジェネリックなどで遊んで始めているので、何か間違ってやっていると助言してください!

答えて

5

あなたのコードは、この行がコンパイルされません。そのため、まったく同じ理由で動作しません:

IRepository<IEntity> repo = new Form64_9C2Repository(); 

基本的にIRepository<IEntity>Form64_9C2IEntityを実装した場合でもIRepository<Form64_9C2>と同じではありません。

IRepositoryインターフェイス上Tジェネリックパラメータがcovariantた場合、これは働いている可能性があり:

public interface IRepository<out T> where T : class, IEntity 
{ 
    IEnumerable<T> Read();  
} 

をしかし残念ながら、これは、それが唯一のメソッドの戻り値の型としてではなく、パラメータとして現れることができることを意味します。あなたのUpdateDelete、およびCreateの方法のためのno-goです。もちろんそのような構造を定義することができます。

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); 
+0

私は本当に理解できませんが、「out T」を大きく変更していますが、残念ながらすべてのCRUDのリポジトリを解決できるようにしたかったのです、Rだけではない。私はあなたがそうする方法を提供しているのを見るが、additioパラメータ。私は、リポジトリとそれに関連するエンティティを "一緒に"して、競合するエンティティを持つ特定のリポジトリを呼び出さないようにすることを本当に望んでいました。ありがとうございます+1、私はすぐに私が本当に達成したいと思っていたものに似た何かを見つけることができないと仮定して受け入れます。 – Kritner

関連する問題