.NET Framework

プロジェクトに存在しないクラスのインスタンスを動的に作成する

C#

using System;
using System.Reflection;
using System.Reflection.Emit;

namespace TypeBuilderNamespace
{
    public static class MyTypeBuilder
    {
        public static void CreateNewObject()
        {
            var myType = CompileResultType();
            var myObject = Activator.CreateInstance(myType);
        }
        public static Type CompileResultType()
        {
            TypeBuilder tb = GetTypeBuilder();
            ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

            // NOTE: assuming your list contains Field objects with fields FieldName(string) and FieldType(Type)
            foreach (var field in yourListOfFields)
                CreateProperty(tb, field.FieldName, field.FieldType);

            Type objectType = tb.CreateType();
            return objectType;
        }

        private static TypeBuilder GetTypeBuilder()
        {
            var typeSignature = "MyDynamicType";
            var an = new AssemblyName(typeSignature);
            AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
            TypeBuilder tb = moduleBuilder.DefineType(typeSignature
                                , TypeAttributes.Public |
                                TypeAttributes.Class |
                                TypeAttributes.AutoClass |
                                TypeAttributes.AnsiClass |
                                TypeAttributes.BeforeFieldInit |
                                TypeAttributes.AutoLayout
                                , null);
            return tb;
        }

        private static void CreateProperty(TypeBuilder tb, string propertyName, Type propertyType)
        {
            FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);

            PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
            MethodBuilder getPropMthdBldr = tb.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
            ILGenerator getIl = getPropMthdBldr.GetILGenerator();

            getIl.Emit(OpCodes.Ldarg_0);
            getIl.Emit(OpCodes.Ldfld, fieldBuilder);
            getIl.Emit(OpCodes.Ret);

            MethodBuilder setPropMthdBldr =
                tb.DefineMethod("set_" + propertyName,
                  MethodAttributes.Public |
                  MethodAttributes.SpecialName |
                  MethodAttributes.HideBySig,
                  null, new[] { propertyType });

            ILGenerator setIl = setPropMthdBldr.GetILGenerator();
            Label modifyProperty = setIl.DefineLabel();
            Label exitSet = setIl.DefineLabel();

            setIl.MarkLabel(modifyProperty);
            setIl.Emit(OpCodes.Ldarg_0);
            setIl.Emit(OpCodes.Ldarg_1);
            setIl.Emit(OpCodes.Stfld, fieldBuilder);

            setIl.Emit(OpCodes.Nop);
            setIl.MarkLabel(exitSet);
            setIl.Emit(OpCodes.Ret);

            propertyBuilder.SetGetMethod(getPropMthdBldr);
            propertyBuilder.SetSetMethod(setPropMthdBldr);
        }
    }
}

VB

Imports System
Imports System.Reflection
Imports System.Reflection.Emit

Public NotInheritable Class CustomType
    Private Sub New()
    End Sub

    Public Shared Function CreateNewObject()
        Dim myType = CompileResultType()
        Dim myObject = Activator.CreateInstance(myType)

        Return myObject
    End Function

    Public Shared Function CompileResultType() As Type
        Dim tb As TypeBuilder = GetTypeBuilder()
        Dim constructor As ConstructorBuilder = tb.DefineDefaultConstructor(MethodAttributes.[Public] Or MethodAttributes.SpecialName Or MethodAttributes.RTSpecialName)

        ' MyObjectInstanceは動的にクラスインスタンスを作成するため、必須な情報を格納している
        For Each col As MyObjectType In MyObjectInstance
            CreateProperty(tb, col.colName, GetType(String))
        Next

        Dim objectType As Type = tb.CreateType()
        Return objectType
    End Function

    Private Shared Function GetTypeBuilder() As TypeBuilder
        Dim typeSignature = "MyDynamicType"
        Dim an = New AssemblyName(typeSignature)
        Dim assemblyBuilder As AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run)
        Dim moduleBuilder As ModuleBuilder = assemblyBuilder.DefineDynamicModule("MainModule")
        Dim tb As TypeBuilder = moduleBuilder.DefineType(typeSignature, TypeAttributes.[Public] Or TypeAttributes.[Class] Or TypeAttributes.AutoClass Or TypeAttributes.AnsiClass Or TypeAttributes.BeforeFieldInit Or TypeAttributes.AutoLayout, Nothing)
        Return tb
    End Function

    Private Shared Sub CreateProperty(tb As TypeBuilder, propertyName As String, propertyType As Type)
        Dim fieldBuilder As FieldBuilder = tb.DefineField("_" & propertyName, propertyType, FieldAttributes.Private)

        Dim propertyBuilder As PropertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, Nothing)
        Dim getPropMthdBldr As MethodBuilder = tb.DefineMethod(propertyName, MethodAttributes.Public Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig, propertyType, Type.EmptyTypes)
        Dim getIl As ILGenerator = getPropMthdBldr.GetILGenerator()

        getIl.Emit(OpCodes.Ldarg_0)
        getIl.Emit(OpCodes.Ldfld, fieldBuilder)
        getIl.Emit(OpCodes.Ret)

        Dim setPropMthdBldr As MethodBuilder = tb.DefineMethod(propertyName, MethodAttributes.Public Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig, Nothing, New Type() {propertyType})

        Dim setIl As ILGenerator = setPropMthdBldr.GetILGenerator()
        Dim modifyProperty As Label = setIl.DefineLabel()
        Dim exitSet As Label = setIl.DefineLabel()

        setIl.MarkLabel(modifyProperty)
        setIl.Emit(OpCodes.Ldarg_0)
        setIl.Emit(OpCodes.Ldarg_1)
        setIl.Emit(OpCodes.Stfld, fieldBuilder)

        setIl.Emit(OpCodes.Nop)
        setIl.MarkLabel(exitSet)
        setIl.Emit(OpCodes.Ret)

        propertyBuilder.SetGetMethod(getPropMthdBldr)
        propertyBuilder.SetSetMethod(setPropMthdBldr)
    End Sub
End Class


月額たった 1,050円で始められる本格的なお店のホームページ!

コメント:



(画像の文字列を入力して下さい)

トップ   編集 凍結 差分 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019/12/02 (月) 12:33:34 (1628d)

e[NȂECir Yahoo yV LINEf[^[Ōz500~`I
z[y[W ̃NWbgJ[h COiq@COsیI COze