C# 内存中的反射和动态程序集

C# 内存中的反射和动态程序集,c#,reflection,C#,Reflection,假设我使用CSharpCodeProvider动态创建了一个类型,并选择不持久化结果。生成的程序集仅存在于内存中。 假设我在两个不同的内存程序集中创建了两种类型: 大会1: public class DynamicTypeA { } 大会2: public class DynamicTypeB { public DynamicTypeA MyProperty { get; set; } } 如您所见,第二种类型具有第一种类型的属性。 酷。现在,我想使用反射探索DynamicTy

假设我使用CSharpCodeProvider动态创建了一个类型,并选择不持久化结果。生成的程序集仅存在于内存中。 假设我在两个不同的内存程序集中创建了两种类型:

大会1:

public class DynamicTypeA { }
大会2:

public class DynamicTypeB
{
       public DynamicTypeA MyProperty { get; set; }
}
如您所见,第二种类型具有第一种类型的属性。 酷。现在,我想使用反射探索DynamicTypeB:

foreach (PropertyInfo pi in typeof(DynamicTypeB).GetProperties())
{
    Console.WriteLine(pi.PropertyType.Name);
}
当程序集不在磁盘上时,PropertyInfo.PropertyType会失败!!! MemberInfo和所有其他类型调查构造都是如此

众所周知,许多.Net API在后端使用类型调查,当调查的类型恰好位于内存程序集中时,它们将失败。例如Expression.Bind将MemberInfo作为第一个参数,并使用它验证第二个参数中提供的表达式类型是否与成员类型匹配。当此类型恰好位于内存中的程序集表达式中时。绑定失败

有人能想出解决办法吗

动态创建类型并将其写入磁盘会污染运行环境,这是不好的,但如果没有反射,这些类型将一文不值

谢谢 马努

当程序集不在磁盘上时,PropertyInfo.PropertyType会失败

你确定吗?看一看:

    static void Main( string[] args )
    {
        string code = @"
             namespace foo {
                 public class DynamicTypeA { }
                 public class DynamicTypeB {
                     public DynamicTypeA MyProperty { get; set; } 
                 }
             }       
        ";

        CSharpCodeProvider csp = new CSharpCodeProvider();

        CompilerParameters p = new CompilerParameters();
        p.GenerateInMemory = true;

        var results = csp.CompileAssemblyFromSource( p, code );

        foreach ( Type type in results.CompiledAssembly.GetTypes() )
        {
            Console.WriteLine( type.Name );

            foreach ( PropertyInfo pi in type.GetProperties() )
            {
                Console.WriteLine( "\t{0}", pi.PropertyType.Name );
            }
        }

        Console.ReadLine();

    }
这使用了你的代码片段,效果很好

将循环移动到动态代码内部不会有太大变化,它仍然有效:

        string code = @"
             using System;
             using System.Reflection; 
             namespace foo {
                 public class DynamicTypeA { }
                 public class DynamicTypeB {
                     public DynamicTypeA MyProperty { get; set; } 
                 }

                 public class DynamicTypeC {
                     public void Foo() {
                        foreach ( PropertyInfo pi in typeof(DynamicTypeB).GetProperties() )
                        {
                            Console.WriteLine( pi.PropertyType.Name );
                        }
                     } 
                 }
             }       
        ";

        CSharpCodeProvider csp = new CSharpCodeProvider();

        CompilerParameters p = new CompilerParameters();
        p.GenerateInMemory = true;

        var results = csp.CompileAssemblyFromSource( p, code );

        var c = results.CompiledAssembly.CreateInstance( "foo.DynamicTypeC" );
        var typeC = c.GetType();

        typeC.InvokeMember( "Foo", BindingFlags.InvokeMethod | 
            BindingFlags.Public | BindingFlags.Instance, null, c, null );
如果出于某种原因,您在这里遇到了问题,那么您肯定是在做更复杂的事情。

我发现了问题: 我需要将动态编译的程序集加载到当前AppDomain中,只有这样,我才能通过反射检索任何信息

我要感谢Sam Alavi向我解释这一点。 以下是带有必要修复的代码:

public class HomeController : Controller
{
    public Assembly AssemblyA { get; set; }
    public Assembly AssemblyB { get; set; }

    public ActionResult Index()
    {
        var provider = new CSharpCodeProvider();
        var parametersA = new CompilerParameters();
        parametersA.GenerateInMemory = true;
        parametersA.OutputAssembly = "dynamicA.dll";

        var code1 = @"namespace DynamicA {  public class DynamicClassA  {  } }";
        var result1 = provider.CompileAssemblyFromSource(parametersA, code1);
        this.AssemblyA = result1.CompiledAssembly;

        var parametersB = new CompilerParameters();
        parametersA.GenerateInMemory = true;
        parametersB.ReferencedAssemblies.Add("dynamicA.dll");
        parametersB.OutputAssembly = "dynamicB.dll";
        var code2 = @"using DynamicA; namespace DynamicB { public class DynamicB { public DynamicClassA MyProperty { get; set; } } }";

        var results2 = provider.CompileAssemblyFromSource(parametersB, code2);
        this.AssemblyB = results2.CompiledAssembly;

        AppDomain.CurrentDomain.AssemblyResolve += (sender, e) =>
        {
            if (e.Name.Contains("dynamicA"))
                return this.AssemblyA;
            if (e.Name.Contains("dynamicB"))
                return this.AssemblyB;
            return null;

        };
        AppDomain.CurrentDomain.Load(this.AssemblyA.FullName);
        AppDomain.CurrentDomain.Load(this.AssemblyB.FullName);


        var t = results2.CompiledAssembly.DefinedTypes.First();
        var pi = t.GetProperty("MyProperty");

         var res = pi.PropertyType.Name;

        return View(res);
    }
}