C# 在运行时为方法生成委托

C# 在运行时为方法生成委托,c#,lambda,reflection,expression,C#,Lambda,Reflection,Expression,我发现这篇有趣的文章 所描述的方法对于属性非常有效。所以我也试图让它在方法上发挥作用,但没有成功 类/属性/方法 public class bmecatContent { private bmecatHeader header; private bmecatCatalog catalog; private List<bmecatFieldValue> fieldValueList; public bmecatContent() {

我发现这篇有趣的文章

所描述的方法对于属性非常有效。所以我也试图让它在方法上发挥作用,但没有成功

类/属性/方法

 public class bmecatContent
{
    private bmecatHeader header;
    private bmecatCatalog catalog;
    private List<bmecatFieldValue> fieldValueList;

    public bmecatContent()
    {
        header = new bmecatHeader();
        catalog = new bmecatCatalog();
    }

    public string DeclarationVersion { get; set; }
    public string DeclarationEncoding { get; set; }
    public string BmecatVersion { get; set; }

    public bmecatHeader Header
    { get { return header; } }
    public bmecatCatalog Catalog
    { get { return catalog; } }

}


public class bmecatCatalog
{
    private List<bmecatCatalogGroupSystem> catalogGroupSystem;
    private List<bmecatClassificationSystem> classificationSystem;
    private List<bmecatProduct> products;
    private List<bmecatProductToCataloggroupMap> productToCataloggroupMap;

    public bmecatCatalog()
    {
        catalogGroupSystem = new List<bmecatCatalogGroupSystem>();
        classificationSystem = new List<bmecatClassificationSystem>();
        products = new List<bmecatProduct>();
        productToCataloggroupMap = new List<bmecatProductToCataloggroupMap>();
    }

    public List<bmecatClassificationSystem> Classification_System
    { get { return classificationSystem; } }
    public List<bmecatCatalogGroupSystem> Catalog_Group_System
    { get { return catalogGroupSystem; } }
    public List<bmecatProduct> Products
    { get { return products; } }
    public List<bmecatProductToCataloggroupMap> Product_To_Cataloggroup_Map
    { get { return productToCataloggroupMap; } }

    public bmecatProduct GetProductByInernationalPid(string Pid)
    {
        // linq
        var query = from prodItem in products
                   from innerList in prodItem.Product_Details.International_PID
                   where innerList.PID == Pid
                   select prodItem;
        return query.FirstOrDefault();

    }
}

这背后的想法是解析给定的类+属性结构,其中用户在映射说明中提供propertynames/methodnames。

为什么您的学员需要一个
对象和
字符串,而
GetPersonByName
只需要
字符串?您可以添加要为哪个方法创建委托吗?如何调用
BuildMethodAccessor
?我假设类似于
Func del=BuildAccessorMethod(typeof(Process).GetMethod(“GetPersonByName”))
,对吗?@HimBromBeere请看一下我所做的更新。希望它变得更清楚,我试图实现在您的更新,似乎您遗漏了一些代码。你能提供完整的上下文吗?或者,您可以提供一个要转换为表达式树的方法吗?我在这方面有很多经验,可能可以帮助你,我只是需要一些更多的信息。特别是如果你提供了
resultmbeccontent
的类型和你想要获得代理的方法,这将是非常有帮助的。无论如何,我强烈地感觉到你的事情过于复杂了。你为什么在这里建表情树?您得到的只是一个
对象
,因此我看不到纯反射或更好的直接成员访问有多大好处。然而,我们没有更清晰的图像,你为什么认为你需要这个。
// Properties
public static Func<object, object> BuildGetAccessor(MethodInfo method)
    {
        var obj = Expression.Parameter(typeof(object), "o");

        Expression<Func<object, object>> expr =
            Expression.Lambda<Func<object, object>>(
                Expression.Convert(
                    Expression.Call(
                        Expression.Convert(obj, method.DeclaringType),
                        method),
                    typeof(object)),
                obj);

        return expr.Compile();

    }

// Methods (with string Parameter)
public static Func<object, string, object> BuildMethodAccessor(MethodInfo method)
    {
        var obj = Expression.Parameter(typeof(object), "o");
        var strParam = Expression.Parameter(typeof(string), "strParam");
        //var param = method.GetParameters().Select(p => Expression.Parameter(p.ParameterType, p.Name)).FirstOrDefault();
        var param = Expression.Convert(strParam, method.GetParameters().First().ParameterType);

        Expression<Func<object, string, object>> expr =
            Expression.Lambda<Func<object, string, object>>(
                Expression.Convert(Expression.Call(Expression.Convert(obj, method.DeclaringType), method, param),
                    typeof(object)),
                obj);

        return expr.Compile();

    }
bmecatParser parser = new bmecatParser();
// parser contains Property BmecatContent of type bmecatContent
// BmecatContent contains all properties and Methods I Need to Access at runtime
// e.g. BmecatContent.Catalog, BmecatContent.Catalog.GetProductByInernationalPid(string Pid)


// gets instance of main-class
var property = parser.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Single(obj => obj.Name == "BmecatContent");
var access = Extensions.BuildGetAccessor(property.GetGetMethod());
var resultBmecatContent = access(parser);

// gets instance of class that holds method
property = resultBmecatContent.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Single(obj => obj.Name == "Catalog");
access = Extensions.BuildGetAccessor(property.GetGetMethod());
var resultCatalog = access(resultBmecatContent);

// here I try to get value from method that has 1 Parameter (string)
var method = resultCatalog.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance).Single(obj => obj.Name == "GetProductByInernationalPid");
var accessProd = Extensions.BuildMethodAccessor(method);
var resultProduct = accessProd(resultCatalog, "4317784548366");