首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将对象文字提供给ILGenerator

将对象文字提供给ILGenerator
EN

Stack Overflow用户
提问于 2009-08-13 04:00:05
回答 2查看 1.6K关注 0票数 5
代码语言:javascript
复制
Food obj = ...;
ILGenerator gen = (...).GetILGenerator();
gen.Emit( ?? obj ?? ); // replace this 
gen.Emit(OpCodes.Call, typeof(Person).GetMethod("Eat"));

这显然不可能干净利落地将obj推到评估堆栈上,但我对丑陋的黑客行为持开放态度,这些黑客行为可能会损害例如可移植性。ModuleBuilder.DefineInitializedData允许用户在.sdata中存储System.Byte[]。有什么想法吗?

Edit:生成的方法将作为新程序集的一部分发出。

EN

回答 2

Stack Overflow用户

发布于 2009-08-13 04:02:41

代码语言:javascript
复制
object o = ...;
Func<object> sneaky = () => o;
gen.Emit(OpCodes.Call, sneaky.Method);

另外,请确保您不能将System.Linq.Expressions用于您的目的。以下是我在ANTLR项目中前后的一段代码:

在此之前。请注意,这里有一个bug (找不到关于它的邮件列表帖子),我没有找到它,因为切换到"After“作为一个副作用更正了它。

代码语言:javascript
复制
private static Func<object, object> BuildAccessor(MethodInfo method)
{
    DynamicMethod dm = new DynamicMethod(method.DeclaringType.Name + method.Name + "MethodAccessor", typeof(object), new Type[] { typeof(object) }, method.DeclaringType);
    var gen = dm.GetILGenerator();

    if (!method.IsStatic)
    {
        gen.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
        gen.Emit(System.Reflection.Emit.OpCodes.Castclass, method.DeclaringType);
    }

    if (method.IsVirtual && !method.IsFinal)
        gen.EmitCall(System.Reflection.Emit.OpCodes.Callvirt, method, null);
    else
        gen.EmitCall(System.Reflection.Emit.OpCodes.Call, method, null);

    if (method.ReturnType.IsValueType)
        gen.Emit(System.Reflection.Emit.OpCodes.Box, method.ReturnType);

    gen.Emit(System.Reflection.Emit.OpCodes.Ret);
    return (Func<object, object>)dm.CreateDelegate(typeof(Func<object, object>));
}

private static Func<object, object> BuildAccessor(FieldInfo field)
{
    DynamicMethod dm = new DynamicMethod(field.DeclaringType.Name + field.Name + "FieldAccessor", typeof(object), new Type[] { typeof(object) }, field.DeclaringType);

    var gen = dm.GetILGenerator();
    if (field.IsStatic)
    {
        gen.Emit(System.Reflection.Emit.OpCodes.Ldsfld, field);
    }
    else
    {
        gen.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
        gen.Emit(System.Reflection.Emit.OpCodes.Castclass, field.DeclaringType);
        gen.Emit(System.Reflection.Emit.OpCodes.Ldfld, field);
    }

    if (field.FieldType.IsValueType)
        gen.Emit(System.Reflection.Emit.OpCodes.Box, field.FieldType);

    gen.Emit(System.Reflection.Emit.OpCodes.Ret);
    return (Func<object, object>)dm.CreateDelegate(typeof(Func<object, object>));
}

之后:

代码语言:javascript
复制
private static Func<object, object> BuildAccessor(MethodInfo method)
{
    ParameterExpression obj = Expression.Parameter(typeof(object), "obj");

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

private static Func<object, object> BuildAccessor(FieldInfo field)
{
    ParameterExpression obj = Expression.Parameter(typeof(object), "obj");

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

    return expr.Compile();
}
票数 1
EN

Stack Overflow用户

发布于 2009-09-09 01:09:13

我建议序列化所需的对象,并发出调用以从资源流(如果您要频繁访问它,则可能是缓存)反序列化它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1269967

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档