使用反射从基类调用方法

时间:2016-12-27 05:48:13

标签: c# generics reflection repository-pattern unit-of-work

我实现了通用存储库模式和单元工作。我使用了基本模式,效果很好。在项目中我有要求说,每个表都有几个字段,其中包含很长很长的文本,用户应该有能力选择并打开任何一个。由于每个字段的名称不同,我决定使用带有反射的power ov泛型,编写释放表名和字段名并返回它的方法。 方法,在通用的Repository类中,我写的看起来像这样,看起来工作正常

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

我使用帮助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 个答案:

答案 0 :(得分:0)

我不确定这是最佳选择,但是使用here的ToExpando()扩展程序解决了问题。通过此扩展,我可以循环抛出unitofwork的所有属性,并按名称查找所需的属性。

# Create your views here.
import pandas as pd
from flask import Flask
from flask import request
app = Flask(__name__)

@app.route('/getfields',methods=['GET','POST'])
def getfields(request):
    df = pd.read_excel('C:\Users\mysite\Rules.xls')
    allfields = df['Field_Name'].unique()
    if request.method == 'GET':

        return render_template('page1.html',allfields=allfields)
    elif request.method == 'POST':
        dropValue = request.form.get(['fieldnames'])
        dfrows = df.loc[df['Field_Name']==dropValue]
        return render_template('page1.html',allfields=allfields,dfrows=dfrows[['rule','rule_type']].to_html())
if __name__ == "__main__":
    app.run()



html code:
    <!doctype html>
    <title>Hello from Flask</title>
    <h1>Hello {{ allfields }}!</h1>
    <form action="/getfields" method='post'> 

    <select name='fieldnames'>
    {% for val in allfields %}
    <option value='{{val}}'>{{val}}</option>
    {% endfor %}
             
    </select> 
    {{dfrows}}
    <input type='submit' value='submit'>
    </form>

现在方法正在调用。可能有更清洁的解决方案,我仍然希望找到这个。现在我将使用这个解决方案,并且意识到我必须阅读并练习很多关于反射,动力学和泛型的知识。 P.S特别感谢Alexei提供了重要的注释和建议