通过反射加载类型 [英] Loading type through Reflection

查看:112
本文介绍了通过反射加载类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个控制台应用程序和两个类库(A和B).我在A类中有"a"类,在B类中有"b"类.
显然,我的程序输入点将是控制台应用程序.在"a"类中,
我正在通过反射加载"b"的类型.

I have a console application and two class libraries say (A and B). I have class "a" in A and class "b" in B.
Obviously my entry poin of program will be the console application. In class "a",
I am loading the type of "b" through reflection.

Type type = null;
            type = Type.GetType(a,A, version=..,token=) //assembly qualified name;
            object obj = Activator.CreateInstance(type);



现在我的问题是,上面的代码在哪里需要B的引用才能起作用.我是否需要类库A中的类库B的引用或控制台应用程序本身,或者我根本不需要它.

为了使我的方案更加具体,我提供了示例示例.
我有一个名为TestType的类库.它具有一个名为TypeA的类.



Now my question is for the above code to work where do i need the reference of B. Do i need the reference of class library B in class library A or the console Application itself or I do not need it at all.

To make my scenario more specific, I am providing my sample example.
I have a class library named TestType. It has a single class named TypeA.

namespace TestType
{
    public class TypeA
    {
        TypeA() { }
    }
}



同样,我还有一个名为TestApp的类库,其中Runner类试图通过
创建TypeA对象. 反思.



Likewise I have another class library named TestApp in which Runner class is trying to create an object of TypeA through
reflection.

namespace TestApp
{
    public static class Runner
    {
        public static void CreateInstance()
        {
            Type t = Type.GetType("TestType.TypeA, TestType, Version=1.0.0.0, Culture=neutral");
        }

    }
}




我有一个控制台应用程序来测试功能.




I have a console application to test the functionaly.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ReflectionTest
{
    class Program
    {
        static void Main(string[] args)
        {
            TestApp.Runner.CreateInstance();
        }
    }
}



现在,当我运行此命令时,"Runner"将返回NULL.但是,当我在"ReflectionTest"中添加"TestType"的引用时,则可以正常工作.
我只想知道,为什么有必要添加反映在控制台应用程序中的类型的引用.相反,我的假设是"TestApp"需要引用"TestType",因为它是返回"TypeA"对象的对象.



Now when I run this, "Runner" returns NULL. But when I add reference of "TestType" in "ReflectionTest" then it works fine.
All I wanted to know is, why is it necessary to add the reference of type being reflected in the console application. Instead my assumption was "TestApp" would need the reference of "TestType" since it is the one which is returning the object of "TypeA".

推荐答案

使用时首先Type.GetType()您必须以字符串形式提供程序集合格名称.

.net加载程序将加载所有需要加载的类型,因此您无需执行任何操作.

一个重要的注意事项是,当您使用反射时,由于Activator返回的对象不是YourType,所以所有代码都将需要使用反射进行属性和方法访问,所以您不能这样做:
First when using Type.GetType() you have to supply the assembly qualified name as a string.

The .net loader will load all the types that needs to be loaded so you don''t have to do anything.

An important note is when you use reflection then all your code will need to be using reflection for property and method access since the Activator returns an object not YourType so you can''t do :
object o = Activator.CreateInstance(type);
o.CallMyMethod(); // error




Type.GetType要求您提供完全限定的程序集名称,它不能与完全限定的类型名称一起使用,因此请执行以下操作:




Type.GetType requires you to supply a fully qualified assembly name, it will not work with the full qualified type name, so do the following :

string[] s = typestr.Split(new char{','},2); // typestr = "TestType.TypeA, TestType, Version=1.0.0.0, Culture=neutral"
object o = Activator.CreateInstance(s[0].Trim(), s[1].Trim());


我假设您已尝试过,现在您想确认您的观察?

只要您不需要加载类型的任何信息(例如调用方法或属性等),就不需要在任何地方进行任何引用.

但是,由于在大多数情况下,您要做需要某种类型的信息,因此这种情况通常是通过接口完成的:该加载的类型实现了一个接口,并且您将创建的对象强制转换为该接口,而不是.然后您只需要知道接口类型(即在项目中具有定义的程序集引用)即可.

例如
I assume you did try it out and now you want a confirmation of your observation?

As long as you don''t need any information from your loaded type (like calling a method or a property, etc.), you don''t need any references anywhere.

But since in most cases you do need some information of that type, such a scenario is usually done via interfaces: that loaded type implements an interface and you cast the created object to that interfaces instead of an object. Then you only need to know the interface type (i.e. have the defining assembly references in the project).

E.g.
// interface assembly I
public interface IMyPlugin
{
   string Name { get; }
   ...
}

// implementation A assembly: reference to assembly I
public class MyPluginA: IMyPlugin
{
   public string Name { get { return m_Name; } }
   ...
}

// main assembly: references only assembly I
...
Dictionary<string, IMyPlugin> m_Plugins = new Dictionary<string, IMyPlugin>();
...
foreach(Type type in LoadMyPluginConfig(...))
{
    IMyPlugin plugin = (IMyPlugin)Activator.CreateInstance(type);
    m_Plugins.Add(plugin.Name, plugin);
}
...


您可能需要看一下 MEF(托管扩展框架) [


You may want to have a look at MEF (Managed Extensibility Framework)[^] to have this kind of activation done for you.

Cheers
Andi


现在我自己尝试了一下,我想我已经找到了您遇到问题的原因:
您会被Visual Studio愚弄.

Visual Studio通常将所有项目引用(静默地)部署到给定C#项目的生成输出文件夹中. IE.当您在主程序项目中添加对LibA和LibB的引用时,它们将被部署在bin \ Debug或bin \ Release文件夹中的主程序旁边.

如果不引用这两个库,则只会将主程序程序集部署到其bin \ Debug或bin \ Release文件夹中.
您观察到的是,由于.NET程序集解析机制无法找到LibA的类型,因此无法对其进行构造.

请执行以下操作:
1)将所有项目的输出文件夹设置为.. \ bin(而不是bin \ Debug或bin \ Release)
2)重新编译解决方案.

现在,所有程序集都在同一个bin文件夹中,.NET可以解析所需的类型.

干杯
安迪

PS:示例代码:


主项目,没有引用LibA和LibB.

Now that I did try it out myself, I think I found the reason for your problem:
you get fooled by Visual Studio.

Visual Studio usually deploys (silently) all the project references to the build output folder of the given C# project. I.e. when you add in the main program project a reference to the LibA and LibB, then they get deployed beside the main program in the bin\Debug or bin\Release folder.

If you do not reference these two libs, you get only the main program assembly deployed to its bin\Debug or bin\Release folder.

What you observe is that the type from LibA can not be constructed since the types could not be found by .NET assembly resolution machinery.

Do the following:
1) set the output folder of all projects to ..\bin (instead of bin\Debug or bin\Release)
2) recompile the solution.

Now, all assemblies are in the same bin folder and .NET can resolve the needed types.

Cheers
Andi

PS: Example code:


Main Project, no references to neither LibA nor LibB.

namespace ConsoleApplication9
{
    class Program
    {
        static void Main(string[] args)
        {
            Type type = Type.GetType("LibA.ClassA, LibA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
            object obj = Activator.CreateInstance(type);
            Console.WriteLine(obj.ToString());
        }
    }
}


有关LibB的LibA:


LibA with reference to LibB:

namespace LibA
{
    public class ClassA
    {
        public ClassB Other { get; set; }
        public ClassA()
        {
            Other = new ClassB();
        }
    }
}


LibB:


LibB:

namespace LibB
{
    public class ClassB
    {
        public void Write(string message)
        {
            Console.WriteLine("Message: {0}", message);
        }
    }
}


  1. 上述步骤
  2. 将程序集手动复制到一个目录(粗体)
  3. 如果产品中有特定的部署结构,请实施程序集解析处理程序


我建议采用第一种方法,因为这是最简单的方法.否则,解析处理程序将有所帮助.


I suggest to go the 1st approach since it is the simplest one. Otherwise, a resolution handler would help.


这篇关于通过反射加载类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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