无法使用表达式创建生成器

Cannot Create Generator using Expressions

我有:

public class HubGroup: HubObject
{
    public HubGroup(elnGroup group)
    {//do stuff}
}

public class elnGroup: elnObject
{
    //has properties
}

我的要求是当我为一个方法提供 2 种类型时,它将生成一个函数,该函数将接受 elnGroup 的对象作为参数和 return HubGroup 的新实例。我尝试了很多东西,但我找不到可以快速完成的方法(这些生成器函数将 运行 几次)

我知道你会说使用泛型,但我的类型是在运行时生成的。我所拥有的只是我可以明确声明的两种类型的基础类。您在下面看到的代码是我的一些片段,只是为了让您了解我正在发生的事情。

所以我这样称呼它:

public class ApiDataHandler
{
    //this will be called by a method to give json content for objEln
    public void SoFunny<T>(string strContent, T objHub) where T : HubObject
    {
        if (typeof(T) == typeof(HubGroup))
        {
            if (string.IsNullOrEmpty(strContant))
            {
                throw new Exception("Cannot parse null/empty string! ---ApiDataHandler---");
            }

            var objEln = JsonConvert.DeserializeObject<elnGroup>(strContant);
            GetHubObjectGenerator(objEln.GetType(), objHub.GetType());
        }
    }
}

我要创建的内容:

Func<object,object> generator = (input) => {var bObj = input as BObject;
                                            var aObj = new AObject(bObj);
                                            return aObj;
                                            }

我已经这样做了:但它一直在说:

InvalidOperationException:'ElnHub.HubObjectModel.elnGroup' 类型的变量 'objEln' 从范围 '' 引用,但未定义

//also inside ApiData Handler class
    public Func<object, object> GetHubObjectGenerator(Type elnObjectType, Type hubObjectType)
    {
        ParameterExpression inputParam = Expression.Parameter(typeof(object), "input");
        ParameterExpression objCastedAsEln = Expression.Parameter(elnObjectType, "objEln");
        ParameterExpression objHub = Expression.Parameter(hubObjectType, "objHub");
        var cast = Expression.TypeAs(inputParam, elnObjectType);
        var assignCast = Expression.Assign(objCastedAsEln, cast);
        var constructor = hubObjectType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { elnObjectType }, null);
        var callingConstructor = Expression.New(constructor, new[] { objCastedAsEln });
        var assignNewObj = Expression.Assign(objHub, callingConstructor);
        var bodyBlock = Expression.Block(new[] { inputParam },
                assignCast,
                assignNewObj,
                objHub
            );
        var l = Expression.Lambda<Func<object, object>>(
                bodyBlock,
                inputParam
            );

        Func<object, object> HubObjectGenerator = l.Compile();

        return HubObjectGenerator;
    }

我也试过发送通用类型,但找不到我的方法。这里有点迷失:

    public Func<T,T1> GetHubObjectGenerator<T,T1>() where T : elnObject where T1 : HubObject
    {
        ParameterExpression argParam = Expression.Parameter(typeof(T), "objEln");
        var constructor = typeof(T1).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance,null,new[] { typeof(T) },null);
        Func<T, T1> HubObjectGenerator = Expression.Lambda<Func<T, T1>>(
                Expression.New(constructor, new[] { argParam, }),
                argParam
            ).Compile();

        return HubObjectGenerator;
    }

你想写这样的东西:

Func<object,object> generator = (input) =>
{
    return new AObject((BObject)input);
}

你需要这样的东西:

public Func<object, object> GetHubObjectGenerator(Type elnObjectType, Type hubObjectType)
{
    var inputParameter = ExpressionParameter(typeof(object), "input");
    var castInput = Expression.Convert(inputParameter, elnObjectType);
    var constructor = hubObjectType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { elnObjectType }, null);
    var instantiation = Expression.New(constructor, castInput);
    var lambda = Expression.Lambda<Func<object, object>>(instantiation, inputParameter);
    return lambda.Compile();
}

您也可以在这里轻松使用泛型,甚至不需要强制转换:

public Func<THub, TEln> GetHubObjectGenerator<THub, TEln>() where THub : HubObject, TEln : elnObject
{
    var inputParameter = ExpressionParameter(typeof(TEln), "input");
    var constructor = typeof(THub).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(TEln) }, null);
    var instantiation = Expression.New(constructor, inputParameter);
    var lambda = Expression.Lambda<Func<THub, TEln>>(instantiation, inputParameter);
    return lambda.Compile();
}

这里我没有使用变量或Expression.Block,因为没有必要。如果确实要创建中间变量,请使用 Expression.VariableExpression.Parameter 仅用于输入参数)。类似于:

public Func<object, object> GetHubObjectGenerator(Type elnObjectType, Type hubObjectType)
{
    var inputParameter = ExpressionParameter(typeof(object), "input");

    var castInputVar = Expression.Variable(elnObjectType, "eln");
    var castInput = Expression.Convert(inputParameter, elnObjectType);
    var castInputAssign = Expression.Assign(castInputVar, castInput);

    var constructor = hubObjectType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { elnObjectType }, null);
    var hubObjectVar = Expression.Variable(hubObjectType, "hub");
    var instantiation = Expression.New(constructor, castInputVar);
    var hubObjectAssign = Expression.Assign(hubObjectVar, instantiation);

    var block = Expression.Block(new[] { castInputVar, hubObjectVar },
        castInputAssign,
        hubObjectAssign,
        hubObject);

    var lambda = Expression.Lambda<Func<object, object>>(block, inputParameter);
    return lambda.Compile();
}