2016-12-27 72 views
1

我實現了通用存儲庫模式和unitofwork。我使用基本模式,他們工作得很好。在項目中,我有要求說,每個表有幾個字段,其中包含長,真正長的文本,用戶應該有能力選擇並打開任何一個。由於每個字段命名不同,我決定使用反射的強大功能,編寫方法來獲取表名和字段名並將其返回。 方法,在通用庫類,我寫這個樣子的,它似乎正常工作使用反射從基類調用方法

public interface IRepository<T> where T : class 
    { 
     //other methods 

     string GetPropertyByName(int id, string property); 
    } 

    public class Repository<T> : IRepository<T> where T : class 
    { 
     // other methods. add, edit, delete... 

     public string GetPropertyByName(int id, string property) 
     { 
      T model = this.Get(id);   
      var obj = model.GetType().GetProperty(property).GetValue(model, null); 
      return obj != null ? obj.ToString() : null; 
     } 
    } 

我creted模型類用於幫助EF表。有些表直接綁定genric存儲庫,而另一些則有單獨的接口及其實現,因爲它們需要額外的方法。例如:

public interface ICompanyRepo : IRepository<COMPANY> 
{ 
    //some methods 
} 

public class CompanyRepo : Repository<COMPANY>, ICompanyRepo 
{ 
    //implementations of interface methods 
} 

而且UOW執行:

public interface IUnitOfWork 
{ 
    ICompanyRepo Company { get; }   
    IRepository<CURRENCY> Currency { get; }   
} 

public class UnitOfWork : IUnitOfWork 
{ 
    static DBEntities _context; 
    private UZMEDEXPORTEntities context 
    { 
     get 
     { 
      if (_context == null) 
       _context = new DBEntities(); 
      return _context; 
     } 
    } 
    public UnitOfWork() 
    { 
     _context = context; 
     Company = new SP_CompanyRepo(); 
     Currency = new Repository<CURRENCY>(); 

    } 

    public ICompanyRepo Company { get; private set; } 
    public IRepository<CURRENCY> Currency { get; private set; } 
} 

我在業務層調用GetPropertyByName()方法的問題。 我嘗試這樣做:

public string GetHistory(string tableName, string fieldName, int id) 
    { 
     var prop = unitOfWork.GetType().GetProperty(tableName); 
     MethodInfo method; 
     method = prop.PropertyType.GetMethod("GetPropertyByName"); //try to find method 
     if(method == null) //if method not found search for interface which contains that method 
      method = prop.PropertyType.GetInterface("IRepository`1").GetMethod("GetPropertyByName"); 
     var res = method.Invoke(prop, new object[] { id, fieldName }); 
     return (string)res; 
    } 

它返回System.Reflection.TargetException。正如我所理解的那樣,這個問題是單位實施的結果。在我的invoke方法中,「prop」是接口類型(ICompanyRepo),但invoke的目標應該是接口實現類,在本例中爲「CompanyRepo」。 我找不到如何識別實施類的類型,並解決這個問題。任何幫助被撥出

+1

注意:「通用方法」在C#中有非常具體的含義 - 在帖子中顯示的代碼沒有顯示任何通用方法 - 請編輯帖子以顯示真正的通用方法(如'Foo ()')或者使用其他一些字代替... –

+0

該方法位於通用類內部,存儲庫因此我認爲調用方法通用也是正確的。 Anywat你是對的,編輯問題的一部分@AlexeiLevenkov –

+1

我明白了。請閱讀[MCVE]關於發佈代碼的指導。根據帖子中提供的代碼,無法知道「TEntity」是特定類型(具有奇怪的命名約定)還是泛型類型的參數。 –

回答

0

我不確定這是最好的選擇,但問題解決使用ToExpando()擴展給予here。有了這個擴展,我可以循環拋出unitofwork的所有屬性,並按名稱查找所需的屬性。

var propValue = unitOfWork.ToExpando().Single(x => x.Key == prop.Name).Value; 
var res = method.Invoke(propValue, new object[] { id, fieldName }); 

現在方法調用正確。可能有更清潔的解決方案,我仍然希望找到這個。現在我要使用這個解決方案,並且意識到我必須閱讀和練習很多關於反射,動態和泛型的知識。 PS特別感謝Alexei對於重要筆記和建議