clr via c# 程序集加载和反射集(一)

1,程序集加载---弱的程序集能够加载强签名的程序集,可是不可相反.不然引用会报错!(可是,反射是没问题的)

//获取当前类的Assembly
Assembly.GetEntryAssembly()
//经过Load方法加载程序集
Assembly.Load
//经过LoadFrom加载指定路径名的程序集--能够时url对象.
Assembly LoadFrom(string path)
//只是反射,并确保程序集中的数据不被执行.
ReflectionOnlyLoadFrom()
ReflectionOnlyLoad(string assembly string)

2,发现程序集中定义的类型

class ReflectionRef
    {
        public static void Demo1()
        {
            string AssemblyName = "s7.net, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d5812d469e84c693, processorArchitecture=MSIL";
            Assembly a = Assembly.Load(AssemblyName);
            Display(0, "{0}'s types:",a.FullName);
            a.ExportedTypes.ToList().ForEach(x => Display(2, "t's FullName is {0}", x.FullName));
            Console.WriteLine();
            a = Assembly.GetEntryAssembly();
            Display(0, "{0}'s types:", a.FullName);
            a.ExportedTypes.ToList().ForEach(x => Display(2, "t's FullName is {0}", x.FullName));


        }
        private static void Display(int indent,string Format,params object[] obj)
        {
            Console.Write(new string(' ', indent * 2));
            Console.WriteLine(Format, obj);
        }

    }

结果:android

s7.net, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d5812d469e84c693's types:
     t's FullName is S7.Net.TcpClientMixins
     t's FullName is S7.Net.Conversion
  2,类型对象的准确含义.ios

//经过实列得到类型
obj.GetType();
//经过Type类的静态函数GetType()
public static Type GetType (string typeName);//必须是FullName
//是否抛出异常和忽略大小写.
public static Type GetType (string typeName, bool throwOnError, bool ignoreCase);
//
参数
typeName
String

要获取的类型的程序集限定名称。 请参阅 AssemblyQualifiedName。 若是该类型位于当前正在执行的程序集中或者 Mscorlib.dll 中,则提供由命名空间限定的类型名称就足够了。api

System.TypeInfo提供了实列成员DeclaredNestedTypes和GetDeclaredNestedType定义了类中嵌套的类型.数组

System.Reflection.Assembly 类型提供了实列成员app

GetType  \\string,输入的类型的全名less

DefinedTypes \\ 返回全部定义的类型的TypeInfo.函数

public virtual System.Collections.Generic.IEnumerable<System.Reflection.TypeInfo> DefinedTypes { get; }

ExportedTypes\\返回全部定义的公共类型ui

public virtual System.Collections.Generic.IEnumerable<Type> ExportedTypes { get; }

type对象是轻量级引用,须要更多的了解类型自己,必须获取一个TypeInfo对象this

TypeInfo ti = typeof(ReflectionRef).GetTypeInfo();

 

  • IsPublic
  • IsSealed
  • IsAbstract
  • IsClass
  • IsValueType
  • 另外一些参数返回:
  • Assembly
  • AssemblyQulifiedName
  • FullName
  • Module

3,经过反射构建派生类的层次结构

  • 批量加载程序集---注意,加载程序集的四个要素

{Name{0},PublicKeyToken={1},version={2},Culture={3}}url

 private static void LoadAssemblies()
        {
            String[] assemblies =
            {
            "System,                    PublicKeyToken={0}",
            "System.Core,               PublicKeyToken={0}",
            "System.Data,               PublicKeyToken={0}",
            "System.Design,             PublicKeyToken={1}",
            "System.DirectoryServices,  PublicKeyToken={1}",
            "System.Drawing,            PublicKeyToken={1}",
            "System.Drawing.Design,     PublicKeyToken={1}",
            "System.Management,         PublicKeyToken={1}",
            "System.Messaging,          PublicKeyToken={1}",
            "System.Runtime.Remoting,   PublicKeyToken={0}",
            "System.Security,           PublicKeyToken={1}",
            "System.ServiceProcess,     PublicKeyToken={1}",
            "System.Web,                PublicKeyToken={1}",
            "System.Web.RegularExpressions, PublicKeyToken={1}",
            "System.Web.Services,       PublicKeyToken={1}",
            "System.Windows.Forms,      PublicKeyToken={0}",
            "System.Xml,                PublicKeyToken={0}",
            };

            String EcmaPublicKeyToken = "b77a5c561934e089";
            String MSPublicKeyToken = "b03f5f7f11d50a3a";

            // Get the version of the assembly containing System.Object
            // We'll assume the same version for all the other assemblies
            Version version = typeof(System.Object).Assembly.GetName().Version;

            // Explicitly load the assemblies that we want to reflect over
            foreach (String a in assemblies)
            {
                String AssemblyIdentity =
                   String.Format(a, EcmaPublicKeyToken, MSPublicKeyToken) +
                      ", Culture=neutral, Version=" + version;
                Assembly.Load(AssemblyIdentity);//在AppDomain中加载程序集
            }
        }
public static void Demo2()
        {
            Assembly[] oldAssembly = AppDomain.CurrentDomain.GetAssemblies();//未加载程序集时的app Domain中的程序集

            LoadAssemblies();//加载程序集
            var newAssemblyName = (from a in AppDomain.CurrentDomain.GetAssemblies()//获取在原程序集中的程序集
                              where Array.IndexOf(oldAssembly, a) >= 0
                              orderby a.FullName
                              select a.FullName).ToArray();

            Array.ForEach<string>(newAssemblyName, x => Display(3, x));//打印原程序集
            Console.WriteLine("Compare Assemblys end");

            var allTypes =
                (from a in AppDomain.CurrentDomain.GetAssemblies()
                 from t in a.ExportedTypes
                 where typeof(MemberInfo).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo())//获取全部派生自Exception的类型.
                 orderby t.Name
                 select t).ToArray();
            Display(0, WalkInheritanceHierachy(new StringBuilder(), 0, typeof(MemberInfo), allTypes).ToString());//迭代打印这些类型.
        }
  • 迭代查找派生关系
private static StringBuilder WalkInheritanceHierachy(StringBuilder sb,int indent,Type baseType,IEnumerable<Type> allTypes)//迭代打印函数
        {
            string spaces = new string(' ', indent * 3);//前缀空格
            sb.AppendLine(spaces + baseType.FullName);//添加基类的全名,新一行.
            foreach(var t in allTypes)
            {
                if (t.GetTypeInfo().BaseType != baseType) continue;//若是这个类不是另外一个类的基列,继续.
                WalkInheritanceHierachy(sb, indent + 1, t, allTypes);//若是找到某个类是派生类,则将这个类做为基类,去查找新的派生类.
            }
            return sb;
        }
  • 结果:

System.Reflection.MemberInfo
    System.Reflection.EventInfo
       System.Runtime.InteropServices.ComAwareEventInfo
    System.Reflection.FieldInfo
       System.Reflection.Emit.FieldBuilder
    System.Reflection.MethodBase
       System.Reflection.ConstructorInfo
          System.Reflection.Emit.ConstructorBuilder
       System.Reflection.MethodInfo
          System.Reflection.Emit.DynamicMethod
          System.Reflection.Emit.MethodBuilder
    System.Reflection.PropertyInfo
       System.Reflection.Emit.PropertyBuilder
    System.Type
       System.Reflection.TypeInfo
          System.Reflection.Emit.EnumBuilder
          System.Reflection.Emit.GenericTypeParameterBuilder
          System.Reflection.Emit.TypeBuilder
          System.Reflection.TypeDelegator

4,BindingFlags

字段

 

CreateInstance 512

建立类的实列,Invoke类的实列调用类的构造器时使用.

 

DeclaredOnly 2

指定当前类上面声明的成员

Default 0

指定未定义任何绑定标志。

DoNotWrapExceptions 33554432  
ExactBinding 65536

未知...

FlattenHierarchy 64

指定应返回层次结构往上的公共成员和受保护静态成员。. 静态成员包括字段、方法、事件和属性。. 不支持嵌套类型。

GetField 1024

指定应返回指定字段的值。此标志会传递给 InvokeMember 方法以获取字段值。

GetProperty 4096

指定应返回指定属性的值。此标志会传递给 InvokeMember 方法以调用属性

IgnoreCase 1

指定在绑定时不该考虑成员名称的大小写。

IgnoreReturn 16777216

在 COM 互操做中用于指定能够忽略成员的返回值。

Instance 4

指定实例成员要包括在搜索中。

InvokeMethod 256

指定要调用的方法。非构造器

此标志会传递给 InvokeMember 方法以调用方法。

NonPublic 32

指定非公共成员要包括在搜索中。

OptionalParamBinding 262144

返回其参数计数与提供的参数数量匹配的成员集。

此绑定标志用于参数具备默认值的方法和使用变量参数 (varargs) 的方法。此标志只应与 InvokeMember(String, BindingFlags, Binder, Object, Object[], ParameterModifier[], CultureInfo, String[]) 结合使用。
使用默认值的参数仅在省略了尾随参数的调用中使用。Parameters with default values are used only in calls where trailing arguments are omitted. 它们必须是位于最后面的参数。
They must be the last arguments.

Public 16

指定公共成员要包括在搜索中。

PutDispProperty 16384

指定应调用 COM 对象上的 PROPPUT 成员。

PutRefDispProperty 32768

指定应调用 COM 对象上的 PROPPUTREF 成员。

SetField 2048

指定应设置指定字段的值。

SetProperty 8192

指定应设置指定属性的值。

Static 8

指定静态成员要包括在搜索中。

SuppressChangeType 131072

未实现。

public class BindingFlagsRef
    {
        public static void Go()
        {
            // BindingFlags.InvokeMethod
            // Call a static method.
            Type t = typeof(TestClass);

            Console.WriteLine();
            Console.WriteLine("Invoking a static method.");
            Console.WriteLine("-------------------------");
            t.InvokeMember("SayHello", BindingFlags.InvokeMethod | BindingFlags.Public |//调用类的静态方法.注意Binder=null,Target=null
                BindingFlags.Static, null, null, new object[] { });

            // BindingFlags.InvokeMethod
            // Call an instance method.
            TestClass c = new TestClass();
            Console.WriteLine();
            Console.WriteLine("Invoking an instance method.");
            Console.WriteLine("----------------------------");
            c.GetType().InvokeMember("AddUp", BindingFlags.InvokeMethod, null, c, new object[] { });//调用实列的方法,注意,Target=c;
            c.GetType().InvokeMember("AddUp", BindingFlags.InvokeMethod, null, c, new object[] { });//调用实列的方法,注意,Target=c;

            // BindingFlags.InvokeMethod
            // Call a method with parameters.
            object[] args = new object[] { 100.09, 184.45 };
            object result;
            Console.WriteLine();
            Console.WriteLine("Invoking a method with parameters.");
            Console.WriteLine("---------------------------------");
            result = t.InvokeMember("ComputeSum", BindingFlags.InvokeMethod , null, null, args);//调用带参数的方法.
            Console.WriteLine("{0} + {1} = {2}", args[0], args[1], result);

            // BindingFlags.GetField, SetField
            Console.WriteLine();
            Console.WriteLine("Invoking a field (getting and setting.)");
            Console.WriteLine("--------------------------------------");
            // Get a field value.
            result = t.InvokeMember("Name", BindingFlags.GetField, null, c, new object[] { });//获取和设定字段.
            Console.WriteLine("Name == {0}", result);
            // Set a field.
            t.InvokeMember("Name", BindingFlags.SetField, null, c, new object[] { "NewName" });
            result = t.InvokeMember("Name", BindingFlags.GetField, null, c, new object[] { });
            Console.WriteLine("Name == {0}", result);

            Console.WriteLine();
            Console.WriteLine("Invoking an indexed property (getting and setting.)");
            Console.WriteLine("--------------------------------------------------");
            // BindingFlags.GetProperty
            // Get an indexed property value.
            int index = 3;
            result = t.InvokeMember("Item", BindingFlags.GetProperty, null, c, new object[] { index });//获取索引器的值.
            Console.WriteLine("Item[{0}] == {1}", index, result);
            // BindingFlags.SetProperty
            // Set an indexed property value.
            index = 3;
            t.InvokeMember("Item", BindingFlags.SetProperty, null, c, new object[] { index, "NewValue" });//设定索引器的值.
            result = t.InvokeMember("Item", BindingFlags.GetProperty, null, c, new object[] { index });
            Console.WriteLine("Item[{0}] == {1}", index, result);

            Console.WriteLine();
            Console.WriteLine("Getting a field or property.");
            Console.WriteLine("----------------------------");
            // BindingFlags.GetField
            // Get a field or property.
            result = t.InvokeMember("Name", BindingFlags.GetField | BindingFlags.GetProperty, null, c,
                new object[] { });
            Console.WriteLine("Name == {0}", result);//获取属性或者字段的对象.
            // BindingFlags.GetProperty
            result = t.InvokeMember("Value", BindingFlags.GetField | BindingFlags.GetProperty, null, c,
                new object[] { });//获取属性或者字段的对象.
            Console.WriteLine("Value == {0}", result);

            Console.WriteLine();
            Console.WriteLine("Invoking a method with named parameters.");
            Console.WriteLine("---------------------------------------");
            // BindingFlags.InvokeMethod
            // Call a method using named parameters.
            object[] argValues = new object[] { "Mouse", "Micky" };
            String[] argNames = new String[] { "lastName", "firstName" };
            t.InvokeMember("PrintName", BindingFlags.InvokeMethod, null, null, argValues, null, null,//指定Named类型的方法.
                argNames);

            Console.WriteLine();
            Console.WriteLine("Invoking a default member of a type.");
            Console.WriteLine("------------------------------------");
            // BindingFlags.Default
            // Call the default member of a type.
            Type t3 = typeof(TestClass2);
            t3.InvokeMember("", BindingFlags.InvokeMethod | BindingFlags.Default, null, new TestClass2(),
                new object[] { });//利用特性MemberDefault,和反射配合指定使用方法.当前是Print.

            // BindingFlags.Static, NonPublic, and Public
            // Invoking a member with ref parameters.
            Console.WriteLine();
            Console.WriteLine("Invoking a method with ref parameters.");
            Console.WriteLine("--------------------------------------");
            MethodInfo m = t.GetMethod("Swap");
            args = new object[2];
            args[0] = 1;
            args[1] = 2;
            //m.Invoke(new TestClass(), args);//和调用有参的形式同样,这是新的办法
            t.InvokeMember("Swap", BindingFlags.InvokeMethod, null, new TestClass(), args);//这是经过type来调用.
            Console.WriteLine("{0}, {1}", args[0], args[1]);

            // BindingFlags.CreateInstance
            // Creating an instance with a parameterless constructor.
            Console.WriteLine();
            Console.WriteLine("Creating an instance with a parameterless constructor.");
            Console.WriteLine("------------------------------------------------------");
            object cobj = t.InvokeMember("TestClass", BindingFlags.Public |//注意3个BindingFlags的应用.
                BindingFlags.Instance | BindingFlags.CreateInstance,
                null, null, new object[] { });//建立类的实列的另一个办法.
            Console.WriteLine("Instance of {0} created.", cobj.GetType().Name);

            // Creating an instance with a constructor that has parameters.
            Console.WriteLine();
            Console.WriteLine("Creating an instance with a constructor that has parameters.");
            Console.WriteLine("------------------------------------------------------------");
            cobj = t.InvokeMember("TestClass", BindingFlags.Public |//建立有参的构造器,而且返回实列.
                BindingFlags.Instance | BindingFlags.CreateInstance,
                null, null, new object[] { "Hello, World!" });
            Console.WriteLine("Instance of {0} created with initial value '{1}'.", cobj.GetType().Name,
                cobj.GetType().InvokeMember("Name", BindingFlags.GetField, null, cobj, null));

            // BindingFlags.DeclaredOnly
            Console.WriteLine();
            Console.WriteLine("DeclaredOnly instance members.");
            Console.WriteLine("------------------------------");
            System.Reflection.MemberInfo[] memInfo =
                t.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Instance |//考虑在本类中建立(非继承,实列,公共)的成员集合.
                BindingFlags.Public);
            for (int i = 0; i < memInfo.Length; i++)
            {
                Console.WriteLine(memInfo[i].Name);
            }

            // BindingFlags.IgnoreCase
            Console.WriteLine();
            Console.WriteLine("Using IgnoreCase and invoking the PrintName method.");
            Console.WriteLine("---------------------------------------------------");
            t.InvokeMember("printname", BindingFlags.IgnoreCase | BindingFlags.Static |//忽略大小写
                BindingFlags.Public | BindingFlags.InvokeMethod, null, null, new object[]
                {"Brad","Smith"});

            // BindingFlags.FlattenHierarchy
            Console.WriteLine();
            Console.WriteLine("Using FlattenHierarchy to get inherited static protected and public members.");
            Console.WriteLine("----------------------------------------------------------------------------");
            FieldInfo[] finfos = typeof(MostDerived).GetFields(BindingFlags.NonPublic | BindingFlags.Public |//NoPublic是Protected对象.
                  BindingFlags.Static | BindingFlags.FlattenHierarchy);//返回受保护静态成员.
            foreach (FieldInfo finfo in finfos)
            {
                Console.WriteLine("{0} defined in {1}.", finfo.Name, finfo.DeclaringType.Name);//DeclaringType...成员所定义的Type
            }

            Console.WriteLine();
            Console.WriteLine("Without FlattenHierarchy.");
            Console.WriteLine("-------------------------");
            finfos = typeof(MostDerived).GetFields(BindingFlags.NonPublic | BindingFlags.Public |
                  BindingFlags.Static);
            foreach (FieldInfo finfo in finfos)
            {
                Console.WriteLine("{0} defined in {1}.", finfo.Name, finfo.DeclaringType.Name);
            }
        }

    }
    public class TestClass
    {
        public String Name;
        private Object[] values = new Object[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

        public Object this[int index]
        {
            get
            {
                return values[index];
            }
            set
            {
                values[index] = value;
            }
        }

        public Object Value
        {
            get
            {
                return "the value";
            }
        }

        public TestClass() : this("initialName") { }
        public TestClass(string initName)
        {
            Name = initName;
        }

        int methodCalled = 0;

        public static void SayHello()
        {
            Console.WriteLine("Hello");
        }

        public void AddUp()
        {
            methodCalled++;
            Console.WriteLine("AddUp Called {0} times", methodCalled);
        }

        public static double ComputeSum(double d1, double d2)
        {
            return d1 + d2;
        }

        public static void PrintName(String firstName, String lastName)
        {
            Console.WriteLine("{0},{1}", lastName, firstName);
        }

        public void PrintTime()
        {
            Console.WriteLine(DateTime.Now);
        }

        public void Swap(ref int a, ref int b)
        {
            int x = a;
            a = b;
            b = x;
        }

    }
    [DefaultMemberAttribute("PrintTime")]
    public class TestClass2
    {
        public void PrintTime()
        {
            Console.WriteLine(DateTime.Now);
        }
    }

    public class Base
    {
        static int BaseOnlyPrivate = 0;
        protected static int BaseOnly = 0;
    }
    public class Derived : Base
    {
        public static int DerivedOnly = 0;
    }
    public class MostDerived : Derived { }
 

 

上面的列子枚举了差很少的一些反射调用一个类中的方法或者字段或者其余的一些用法

5,Binder-----从候选者列表中选择一个成员,并执行实参类型到形参类型的类型转换,须要实现派生

   Binder用来自定义选择匹配的方法,字段等...通常不用,或者使用Type.DefaultBinder使用.

6,构造类的实列

    经过反射构造类的实列经常使用方法:

public static void CallCreateObjectByReflection()
        {
            //方法1,使用createInstance--type方法.
            Type t = typeof(TestClass);
            TestClass t1 = (TestClass)Activator.CreateInstance(t, new object[] {  });
            Display(0, t1.Name);
            //方法2,使用程序集的方法,第一个参数能够是null,当前程序集,或者是Assembly.GetEnterAssembly.ToString(),返回程序集的全名.
            var t2 = (TestClass)Activator.CreateInstance(null, typeof(TestClass).FullName).Unwrap();
            Display(0, Assembly.GetEntryAssembly().ToString());
            Display(0, t2.Name);
            //方法3,使用CreateInstanceFrom生成.
            var path = Assembly.GetEntryAssembly().CodeBase;
            var t3 = (TestClass)Activator.CreateComInstanceFrom(path, typeof(TestClass).FullName).Unwrap();
            Display(0, "path is {0},type is {1}", path, t3);
            //方法4,使用AppDomain的CreateInstance;注意,若是是另外的appDomain则须要类型是MarshalRefObject的派生类,或者可序列化对象.
            AppDomain ad0 = AppDomain.CreateDomain("Ad0");
            var t4=AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(path, typeof(TestClass).FullName);
            Display(0, "path is {0},type is {1}", path, t4);
            //方法5,使用InVokeMember调用构造器.
            var t5 = (TestClass)t.InvokeMember("", BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, null);
            Display(0, t5.Name);
            //方法6,使用ConstructorInfo,其实相似上面的
            ConstructorInfo ci = t.GetConstructor(new Type[] { typeof(string) });
            var t6=(TestClass)ci.Invoke(new object[] { "new Constructor" });
            Display(0, t6.Name);
            //方法7,数组类型建立实列
            Array t7 = Array.CreateInstance(t, 10);
            for(int i=0;i<t7.Length;i++)
            {
                t7.SetValue(new TestClass(i.ToString()), i);
            }
            int count=0;
            Array.ForEach<TestClass>((TestClass[])t7, x => Display(count++, x.Name));
            //方法7_1,另一个方法建立数组的实列.
            Type t71 = t.MakeArrayType();
            var t72 =(TestClass[]) Activator.CreateInstance(t71, new object[] { 10 });
            Display(0, t72.Length.ToString());

            //方法8,委托类型建立实列
            MethodInfo mi = t.GetMethod("AddUp");
            var t8 = new TestClass();
            Delegate d = Delegate.CreateDelegate(typeof(Action), t8, mi);
            d.DynamicInvoke();
            d.DynamicInvoke();

            //方法9,构造泛型实列
            Type openType = typeof(Dictionary<,>);//首先建立openType
            Type closeType = openType.MakeGenericType(typeof(string),typeof(string));//建立封闭Type
            Type ListOpenType = typeof(List<>);//建立新的OpenType
            Type ListCloseType = ListOpenType.MakeGenericType(closeType);//建立复合的封闭对象
            object o = Activator.CreateInstance(ListCloseType);//建立类型对象的实列.
            Display(0, o.ToString());


        }

    }

7,设计支持加载项的程序.

    Rainbow  在使用过程当中发现System.IO.FileLoadException错误,的缘由为:

  • 若是某个类是强名称,那么全部它引用的类也必须都是强名称.

        我由于忘记给HostSDK进行强名称设定,因此出错.HostSDK进行以后,AddIn也要进行.

     1,设计接口类:

//HostSDK.cs
using System;

namespace Winteliect.HostSDK
{
	public interface IAddin
	{
		string DoSomeThing(Int32 x);

	}

}

  2,设计接口实现类

//AddInTypes.cs
using System;
using Winteliect.HostSDK;

namespace AddInTypes
{
	public sealed class AddIn_A:IAddin
	{
		public AddIn_A(){}
		public string DoSomeThing(Int32 x)
		{
			return "AddIn_A:"+x.ToString();
		}
	}
	public sealed class AddIn_B:IAddin
	{
		public AddIn_B(){}
		public string DoSomeThing(Int32 x)
		{
			return "AddIn_B:"+(2*x).ToString();
		}
	}
}

      3,进行编译dll

  • sn -k host.snk
  • csc.exe /out:HostSDK.dll /t:library /keyfile:host.snk HostSDK.cs---生成HostSDK.dll
  • csc.exe /out:AddInTypes.dll /t:library /r:HostSDK.dll /keyfile:host.snk AddInTypes.cs---生成AddInTypes.dll

      4,在程序中使用

public static void DynamicLoadDemo()
        {

            string path = Assembly.GetExecutingAssembly().Location;//获取.exe的详细路径
            string AddInDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);//获取.exe的目录.../Debug
            var dlls = Directory.EnumerateFiles(AddInDir, "*.dll");//
            var types =
                (from file in dlls
                let asb = Assembly.LoadFrom(file)
                from t in asb.ExportedTypes
                where t.IsPublic && t.IsClass && (typeof(IAddin).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo()))
                select t).ToList();//获取有该接口的类.

            types.ForEach(//建立类的实列而且工做.
                x =>
                {
                    IAddin t = (IAddin)Activator.CreateInstance(x);
                    Display(0,t.DoSomeThing(10));

                });
        }
相关文章
相关标签/搜索