C# 如何发出委托或lambda表达式

C# 如何发出委托或lambda表达式,c#,delegates,lambda,reflection.emit,C#,Delegates,Lambda,Reflection.emit,我想发出一个返回Func的方法。在这个方法中,我必须创建一个委托或一个lambda表达式,它正好服务于返回类型 总之,它应该是这样的: // I have a resolve method that will be called inside my missing method // This is it's signature: object Resolve( params object[] args); // This is how I use it: var barFactory = (

我想发出一个返回Func的方法。在这个方法中,我必须创建一个委托或一个lambda表达式,它正好服务于返回类型

总之,它应该是这样的:

// I have a resolve method that will be called inside my missing method
// This is it's signature:
object Resolve( params object[] args);

// This is how I use it:
var barFactory = ( Func<IBar> )MissingMethod( typeof( IBar ) );
var bar = barFactory.Invoke();

// or - with one string argument:
var fooFactory = ( Func<string, IFoo> )MissingMethod( typeof( IFoo ), typeof( string ) );
var foo = fooFactory.Invoke( "argument for foo" );
Container.Resolve<Foo>( "argument" );
我的代表应该看起来像

delegate void object LateBoundMethod( object[] arguments );
并且目标作为实例字段提供。通过采用和“改进”Marc的解决方案,我得到:

private Delegate CreateDelegate( Type returnType, Type[] parameterTypes )
{
  m_Type = returnType;

  var i = 0;
  var param = Array.ConvertAll( parameterTypes, arg => Expression.Parameter( arg, "arg" + i++ ) );
  var asObj = Array.ConvertAll( param, p => Expression.Convert( p, typeof( object ) ) );
  var argsArray = Expression.NewArrayInit( typeof( object ), asObj );

  var callEx = Expression.Call( null, typeof( FuncFactory ).GetMethod( "Resolve" ), argsArray );
  var body = Expression.Convert( callEx, returnType );

  var ret = Expression.Lambda( body, param ).Compile();
  return ret;
}

private readonly Container m_Container;
private Type m_Type;

public object Resolve( params object[] args )
{
  return m_Container.Resolve( m_Type, args );
}
但这是不完整的。Resolve()-方法不再是静态的(因为它需要两个实例字段),因此无法调用。所以这里的问题是

var callEx = Expression.Call( null, typeof( FuncFactory ).GetMethod( "Resolve" ), argsArray );

我想我需要一个对“this”的引用,而不是将null作为第一个参数传递。如何做到这一点?

第一个问题是
Func
不存在-您需要分别编码到
Func
Func
Func
Func

现在;我理解代码,但我不确定您试图解决的场景是什么。。。你能澄清一下吗?也许有更好的选择

如果它像听起来一样复杂,那么定制的
表达式
可能是最合适的选择(远比
Reflection.Emit
简单)


例如,这是有效的

static Delegate MissingFunc(Type result, params Type[] args)
{
    int i = 0;
    var param = Array.ConvertAll(args,
        arg => Expression.Parameter(arg, "arg" + i++));
    var asObj = Array.ConvertAll(param,
        p => Expression.Convert(p, typeof(object)));
    var argsArray = Expression.NewArrayInit(typeof(object), asObj);
    var body = Expression.Convert(Expression.Call(
                null, typeof(Program).GetMethod("Resolve"),
                argsArray), result);
    return Expression.Lambda(body, param).Compile();
}
static void Main()
{
    var func2 = MissingFunc(typeof(string), typeof(int), typeof(float));
}
public static object Resolve( params object[] args) {
    throw new NotImplementedException();
}

我得说我不是100%确定我明白了你想要做的事情,但是让MissingMethod泛化不会让你解决问题的一半吗?或者这不是一个选项?哦,还有,我确实知道,你必须对它进行多次编码,以涵盖所有可能的Func泛型,但正如Marc所提到的,你无论如何都必须硬编码。通过编辑,我仍然不明白规则是什么。。。你希望它在[注入]时注入什么?为什么?谢谢你的回复。关于Func你是对的-我必须将接受的参数限制为四个。我想将代码与Resolve()方法(由IoC容器提供)解耦。相反,我希望能够创建小工厂(作为Func参数传递),通过间接使用IoC-container,使对象能够创建一种类型的多个实例。谢谢。。。我不熟悉表达。您能告诉我如何使Resolve()成为签名为“object Resolve(Type,params object)”的实例方法吗?我还是被卡住了:/对不起,我得去坐火车了;我可以在很大程度上详细阐述这个领域,但首先我要重复我的问题:这里的情况是什么?我至少可以用3种方法来处理这个问题(其中没有一种是Reflection.Emit)。。。如果它是一个实例方法。。。这是一个什么样的例子?也许你可以展示一点半完整的。如果你还不确定的话,可以随意取消这个标记作为答案——我不会生气的。只有当你对问题的解决感到满意时才将其标记为完成(我不确定它是…)我接受了你的答案,因为我确信它为我提供了有用的信息:)我只需要找出如何用表达式调用实例方法“object Resolve(Type,params object)”。我编辑了我的帖子-希望它能澄清我想做什么。。。
private Delegate CreateDelegate( Type returnType, Type[] parameterTypes )
{
  m_Type = returnType;

  var i = 0;
  var param = Array.ConvertAll( parameterTypes, arg => Expression.Parameter( arg, "arg" + i++ ) );
  var asObj = Array.ConvertAll( param, p => Expression.Convert( p, typeof( object ) ) );
  var argsArray = Expression.NewArrayInit( typeof( object ), asObj );

  var callEx = Expression.Call( null, typeof( FuncFactory ).GetMethod( "Resolve" ), argsArray );
  var body = Expression.Convert( callEx, returnType );

  var ret = Expression.Lambda( body, param ).Compile();
  return ret;
}

private readonly Container m_Container;
private Type m_Type;

public object Resolve( params object[] args )
{
  return m_Container.Resolve( m_Type, args );
}
var callEx = Expression.Call( null, typeof( FuncFactory ).GetMethod( "Resolve" ), argsArray );
static Delegate MissingFunc(Type result, params Type[] args)
{
    int i = 0;
    var param = Array.ConvertAll(args,
        arg => Expression.Parameter(arg, "arg" + i++));
    var asObj = Array.ConvertAll(param,
        p => Expression.Convert(p, typeof(object)));
    var argsArray = Expression.NewArrayInit(typeof(object), asObj);
    var body = Expression.Convert(Expression.Call(
                null, typeof(Program).GetMethod("Resolve"),
                argsArray), result);
    return Expression.Lambda(body, param).Compile();
}
static void Main()
{
    var func2 = MissingFunc(typeof(string), typeof(int), typeof(float));
}
public static object Resolve( params object[] args) {
    throw new NotImplementedException();
}