HOWTO发出委托或lambda表达式 [英] Howto emit a delegate or lambda expression

查看:133
本文介绍了HOWTO发出委托或lambda表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

欲发射一个返回Func键℃的方法;>。 。在此方法我要创建一个委托或正好服务于返回类型的lambda表达式

I want to emit a method that returns a Func<>. Inside this method I have to create a delegate or a lambda expression which exactly serves the return type.

总之它应该是这样的:

// 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" );



MissingMethod(内部)它应该看起来像:

Inside the MissingMethod() it should look like:

object MissingMethod( Type returnType, params Type[] argTypes )
{
  // Create the type of Func<> based on the passed returnType and the argTypes
  var funcType = typeof(Func<,...,>).MakeGenericType( ... )

  // Here I have to use the Resolve() method and cast the lambda to the correct type
  return (cast to funcType)( (arg1, arg2) => Resolve( arg1, arg2 ) );
}



我觉得让我MissingMethod()的唯一方法是,使用Reflection.Emit的。

I think that the only way to get my MissingMethod() is, to use reflection.emit.

你知道发光的lambda或委托良好的资源或教程?

Do you know good resources or tutorials about emitting a lambda or a delegate?

待办事项你看这个问题的另一种可能的解决方案。

Do you see another possible solution for this problem?

编辑:
这里是什么,我想才达到一个情景:


Here is a scenario of what I want to achive:

static void Main()
{
  var container = new Container();
  container.Register<Foo>();
  container.Register<ConsumerClass>();

  var consumerClass = Container.Resolve<ConsumerClass>();
}

class Foo()
{
  public Foo( string argument ) {}
}

class ConsumerClass
{
  public ConsumerClass( [Inject] Func<string, Foo> factory )
  {
    var foo1 = factory.Invoke( "first foo" );
    var foo2 = factory.Invoke( "another foo" );
    // ...
  }
}



我试图实现容器和resolve()方法。我知道有注册了富的类型。我知道,它的构造需要调用一个字符串。

I am trying to implement the Container and the Resolve() method. I know that there is a "Foo" type registered. And I know that its constructor needs a string to be invoked.

当我必须解决的类型ConsumerClass我看,它希望得到一个Func键注射。这不正是我的容器可以提供,因为通常它提供了单instaces到美孚这样的:

When I have to resolve the type "ConsumerClass" I see that it wants to get a Func injected. That is not exactly what my container can provide, because normally it provides single instaces to Foo like this:

Container.Resolve<Foo>( "argument" );



但尽管如此容器应能提供Func键了。它有需要的所有信息。

But nevertheless the container should be able to provide a Func, too. It has all informations needed.

但现在我被困在创建这个约束Func键<,>。和remeber它可能是一个函数功能&下; ,,,>得。所以我寻找可以动态创建我的这名代表的解决方案。他们必须被强制转换为确切的bound类型

But now I am stuck in creating this bound Func<,>. And remeber it could be a Func<,,,>, too. So I am looking for a solution that can create my this delegates on the fly. They have to be castable to the exact bound type.

编辑:

我不知道该怎么形容更好......我试图做类似的这个。但我并不想传递一个目标。而不是


I am not sure how to describe it better ... I am trying to do something like this. But I do not want to pass a target. Instead of

delegate void object LateBoundMethod( object target, object[] arguments );



我的委托应该像

my delegate should look like

delegate void object LateBoundMethod( object[] arguments );

和目标是作为一个实例字段。通过采取和'改善'马克的解决方案,我得到:

and the target is provided as an instance field. By taking and 'improving' the solution of Marc I get:

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



但是,这是不完整的。决心() - 方法不是静态的了(因为它需要两个实例字段),并且不能被调用。所以这里的问题是

But this is incomplete. The Resolve()-method is not static anymore (because it needs two instance fields) and cannot be called. So the problem here is

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



。我该怎么做了。

Instead of passing null as the first argument I think I need a reference to 'this'. How do I do that?

推荐答案

第一个问题是, Func键< ...> 不存在 - 你需要的代码 Func键<> Func键<,> Func键< ,,> Func键< ,,,方式> 单独

The first problem is that Func<...> doesn't exist - you'd need to code to Func<>, Func<,>, Func<,,>, Func<,,,> separately.

现在;我理解的代码,但是我不知道该方案是什么,你要解决...你能澄清?有可能是更好的选择...

Now; I understand the code, but I'm not sure what the scenario is that you are trying to solve... can you clarify? There are probably better options...

如果是复杂,因为它听起来,一个自定义的表达式可能是最合适的方案。

If it is as complex as it sounds, a custom Expression is probably the most appropriate option (far simpler than 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();
}

这篇关于HOWTO发出委托或lambda表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆