2016-12-27 71 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对于重要笔记和建议