簡體   English   中英

C# 反射:如何發出類

[英]C# Reflection: How to Emit a class

我有一個類,ReferenceObject,我想將它發送到我創建的 dll 中。 如何在不使用 Emit 編寫每個方法的情況下執行此操作? 我基本上希望將這個類添加到我生成的 dll 中。

這是課程:

public class ReferenceObject
{
    private readonly int value;

    public ReferenceObject(int pValue)
    {
        value = pValue;
    }

    public override string ToString()
    {
        return value.ToString();
    }

    public int Value()
    {
        return value;
    }

    public int ID()
    {
        return value;
    }

    #region == Operator

    public static bool operator ==(int objLeft, ReferenceObject objRight)
    {
        return objLeft == objRight.value;
    }

    public static bool operator ==(ReferenceObject objLeft, int objRight)
    {
        return objLeft.value == objRight;
    }

    public static bool operator ==(string objLeft, ReferenceObject objRight)
    {
        return objLeft == objRight.value.ToString();
    }

    public static bool operator ==(ReferenceObject objLeft, string objRight)
    {
        return objLeft.value.ToString() == objRight;
    }

    #endregion

    #region != Operator

    public static bool operator !=(int objLeft, ReferenceObject objRight)
    {
        return objLeft != objRight.value;
    }

    public static bool operator !=(ReferenceObject objLeft, int objRight)
    {
        return objLeft.value != objRight;
    }

    public static bool operator !=(string objLeft, ReferenceObject objRight)
    {
        return objLeft != objRight.value.ToString();
    }

    public static bool operator !=(ReferenceObject objLeft, string objRight)
    {
        return objLeft.value.ToString() != objRight;
    }

    #endregion

    public override bool Equals(object obj)
    {
        if ((obj is ReferenceObject))
            return value == ((ReferenceObject)obj).value;

        if ((obj is int))
            return value == (int)obj;

        if ((obj is string))
            return value.ToString() == (string)obj;

        return false;
    }

    public override int GetHashCode()
    {
        return value;
    }
}

這是我用來生成 .dll 的代碼

AppDomain domain = AppDomain.CurrentDomain;

AssemblyName aName = new AssemblyName("DynamicEnums");
AssemblyBuilder ab = domain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Save);

ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");

ConstructorInfo referenceObjectConstructor = typeof(ReferenceObject).GetConstructor(new[] { typeof(int) });

List<Type> types = new List<Type>();

foreach(ReferenceType rt in GetTypes())
{
    TypeBuilder tb = mb.DefineType(rt.Name, TypeAttributes.Public | TypeAttributes.BeforeFieldInit);

    ConstructorBuilder staticConstructorBuilder = tb.DefineConstructor(MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes);
    ILGenerator staticConstructorILGenerator = staticConstructorBuilder.GetILGenerator();

    foreach (Reference r in GetReferences(rt.ID))
    {
        name = NameFix(r.Name);

        // Create a public, static, readonly field to store the
        // named ReferenceObject.
        FieldBuilder referenceObjectField = tb.DefineField(name, typeof(ReferenceObject), FieldAttributes.Static | FieldAttributes.Public | FieldAttributes.InitOnly);

        // Add code to the static constructor to populate the
        // ReferenceObject field:

        // Load the ReferenceObject's ID value onto the stack as a
        // literal 4-byte integer (Int32).
        staticConstructorILGenerator.Emit(OpCodes.Ldc_I4, r.ID);

        // Create a reference to a new ReferenceObject on the stack
        // by calling the ReferenceObject(int32 pValue) reference
        // we created earlier.
        staticConstructorILGenerator.Emit(OpCodes.Newobj, referenceObjectConstructor);

        // Store the ReferenceObject reference to the static
        // ReferenceObject field.
        staticConstructorILGenerator.Emit(OpCodes.Stsfld, referenceObjectField);
    }
    staticConstructorILGenerator.Emit(OpCodes.Ret);

    types.Add(tb.CreateType());
}

ab.Save(aName.Name + ".dll");

查看 Reflector 的 Reflection.Emit 插件:

你可以在這里下載反射器:
http://www.reflector.net/

這是加載項的鏈接:
http://reflectoraddins.codeplex.com/wikipage?title=ReflectionEmitLanguage&referringTitle=Home

編輯

您可能還想看看這篇文章:
http://www.codeproject.com/KB/dotnet/Creating_Dynamic_Types.aspx

回應評論。

那么為什么不直接使用 CodeDom,或者只使用或編寫一個“離線”代碼生成器? Reflection.Emit 僅在您想在運行時創建類型時才需要,否則它幾乎是矯枉過正。

有關我多年前所做的示例,請參見此處

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM