Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 动态加载DLL_C#_.net - Fatal编程技术网

C# 动态加载DLL

C# 动态加载DLL,c#,.net,C#,.net,我有以下主要方法。LocalCabelTV和LocalDishTV类位于主应用程序中。程序运行良好 我想将LocalCabelTV和LocalDishTV保存在单独的dll文件中。我想知道如何在运行时加载这些类?我知道我们不会使用switch,而是for循环来查找在特定目录中实现IVideSource接口的所有dll文件,并加载这些文件 需要知道如何动态加载DLL、创建对象和使用它们的方法吗? foreach (string dll in Directory.GetFiles("C:\DLLs\

我有以下主要方法。LocalCabelTV和LocalDishTV类位于主应用程序中。程序运行良好

我想将LocalCabelTV和LocalDishTV保存在单独的dll文件中。我想知道如何在运行时加载这些类?我知道我们不会使用switch,而是for循环来查找在特定目录中实现IVideSource接口的所有dll文件,并加载这些文件

需要知道如何动态加载DLL、创建对象和使用它们的方法吗?

foreach (string dll in Directory.GetFiles("C:\DLLs\*.dll"))
{
    Assembly assemb = Assembly.LoadFrom(dll);
    ??
}
以下操作很好:

static void Main(string[] args)
{
   SmartTv myTv = new SmartTv();

   Console.WriteLine("Select A source to get TV Guide and Play");
   Console.WriteLine("1. Local Cable TV\n2. Local Dish TV");

   ConsoleKeyInfo input = Console.ReadKey();

   switch (input.KeyChar)
   {
      case '1':
          myTv.VideoSource = new LocalCabelTv();
          break;

      case '2':
          myTv.VideoSource = new LocalDishTv();
          break;
   }

   Console.WriteLine(); 

   myTv.ShowTvGuide();

   myTv.PlayTV();

   Console.ReadKey();
}

class SmartTv
    {
        IVideoSource currentVideoSource = null;

        public IVideoSource VideoSource
        {
            get
            {
                return currentVideoSource;
            }
            set
            {
                currentVideoSource = value;
            }
        }

        public void ShowTvGuide()
        {
            if (currentVideoSource != null)
            {
                Console.WriteLine(currentVideoSource.GetTvGuide());
            }
            else
            {
                Console.WriteLine("Please select a Video Source to get TV guide from");
            }
        }

        public void PlayTV()
        {
            if (currentVideoSource != null)
            {
                Console.WriteLine(currentVideoSource.PlayVideo());
            }
            else
            {
                Console.WriteLine("Please select a Video Source to play");
            }
        }
class LocalCabelTv : IVideoSource
    {
        const string SOURCE_NAME = "Local Cabel TV";

        string IVideoSource.GetTvGuide()
        {
            return string.Format("Getting TV guide from - {0}", SOURCE_NAME);
        }

        string IVideoSource.PlayVideo()
        {
            return string.Format("Playing - {0}", SOURCE_NAME);
        }
    }
class LocalDishTv : IVideoSource
    {
        const string SOURCE_NAME = "Local DISH TV";

        string IVideoSource.GetTvGuide()
        {
            return string.Format("Getting TV guide from - {0}", SOURCE_NAME);
        }

        string IVideoSource.PlayVideo()
        {
            return string.Format("Playing - {0}", SOURCE_NAME);
        }
    }

class SmartTv
    {
        IVideoSource currentVideoSource = null;

        public IVideoSource VideoSource
        {
            get
            {
                return currentVideoSource;
            }
            set
            {
                currentVideoSource = value;
            }
        }

        public void ShowTvGuide()
        {
            if (currentVideoSource != null)
            {
                Console.WriteLine(currentVideoSource.GetTvGuide());
            }
            else
            {
                Console.WriteLine("Please select a Video Source to get TV guide from");
            }
        }

        public void PlayTV()
        {
            if (currentVideoSource != null)
            {
                Console.WriteLine(currentVideoSource.PlayVideo());
            }
            else
            {
                Console.WriteLine("Please select a Video Source to play");
            }
        }
class LocalCabelTv : IVideoSource
    {
        const string SOURCE_NAME = "Local Cabel TV";

        string IVideoSource.GetTvGuide()
        {
            return string.Format("Getting TV guide from - {0}", SOURCE_NAME);
        }

        string IVideoSource.PlayVideo()
        {
            return string.Format("Playing - {0}", SOURCE_NAME);
        }
    }
class LocalDishTv : IVideoSource
    {
        const string SOURCE_NAME = "Local DISH TV";

        string IVideoSource.GetTvGuide()
        {
            return string.Format("Getting TV guide from - {0}", SOURCE_NAME);
        }

        string IVideoSource.PlayVideo()
        {
            return string.Format("Playing - {0}", SOURCE_NAME);
        }
    }

class SmartTv
    {
        IVideoSource currentVideoSource = null;

        public IVideoSource VideoSource
        {
            get
            {
                return currentVideoSource;
            }
            set
            {
                currentVideoSource = value;
            }
        }

        public void ShowTvGuide()
        {
            if (currentVideoSource != null)
            {
                Console.WriteLine(currentVideoSource.GetTvGuide());
            }
            else
            {
                Console.WriteLine("Please select a Video Source to get TV guide from");
            }
        }

        public void PlayTV()
        {
            if (currentVideoSource != null)
            {
                Console.WriteLine(currentVideoSource.PlayVideo());
            }
            else
            {
                Console.WriteLine("Please select a Video Source to play");
            }
        }
class LocalCabelTv : IVideoSource
    {
        const string SOURCE_NAME = "Local Cabel TV";

        string IVideoSource.GetTvGuide()
        {
            return string.Format("Getting TV guide from - {0}", SOURCE_NAME);
        }

        string IVideoSource.PlayVideo()
        {
            return string.Format("Playing - {0}", SOURCE_NAME);
        }
    }
class LocalDishTv : IVideoSource
    {
        const string SOURCE_NAME = "Local DISH TV";

        string IVideoSource.GetTvGuide()
        {
            return string.Format("Getting TV guide from - {0}", SOURCE_NAME);
        }

        string IVideoSource.PlayVideo()
        {
            return string.Format("Playing - {0}", SOURCE_NAME);
        }
    }

要在运行时加载此程序集并创建对象,请执行以下操作:

Assembly MyDALL = Assembly.Load("DALL"); // DALL is name of my dll
Type MyLoadClass = MyDALL.GetType("DALL.LoadClass"); // LoadClass is my class
object obj = Activator.CreateInstance(Type.GetType("DALL.LoadClass, DALL", true));
对于动态方法,也可以使用动态方法。其速度比反射快(此方法仅需Activator所需时间的十分之一)

下面是使用动态方法创建对象的示例代码

void CreateMethod(ConstructorInfo target)
{
    DynamicMethod dynamic = new DynamicMethod(string.Empty,
                typeof(object),
                new Type[0],
                target.DeclaringType);

    methodHandler = (MethodInvoker)dynamic.CreateDelegate(typeof(MethodInvoker));
}
有关更多信息,请查看以下链接:


编辑:正如user@taffer提到的,DynamicMethod.CreateDelegate比反射慢得多。因此,只有在创建的委托被调用数百次或数千次时,我才会使用它。使用带缓存的Activator更快。其次,Activator对于无参数构造函数的速度非常快,除非你实例化了太多类型,这使得内部的小缓存变得无用。

你需要用所需的类加载DLL并迭代它们的类型,而不是寻找那些实现了
ivideource
的类并激活它们:

public static IEnumerable<IVideoSource> GetVideoSources(List<string> assemblyPathes)
{
    IEnumerable<Assembly> yourAssembliesWithClasses = assemblyPathes.Select(x => Assembly.Load(x));

    IEnumerable<Type> implementingTypes = yourAssembliesWithClasses
        .GetTypes()
        .Where(x => x.IsAssignableFrom(IVideoSource));

    return implementingTypes.Select(x => Activator.CreateInstance(x));
}
公共静态IEnumerable GetVideoSources(列表汇编路径)
{
IEnumerable yourAssembliesWithClasses=AssemblyPaths.Select(x=>Assembly.Load(x));
IEnumerable implementingTypes=YourAssembliesWithClass
.GetTypes()
其中(x=>x.IsAssignableFrom(IVideoSource));
返回implementingTypes.Select(x=>Activator.CreateInstance(x));
}

请注意,
Activator.CreateInstance()
要求类型具有空构造函数,如果它们没有可以使用的构造函数,
Type.GetUniGetUninitializedObject(Type)
FormatterServices
初始化它们。

您不想使用
反射生成代码。发出
除非您确实必须。。。想想那个可怜的程序员,他将取代你,不得不学习这些代码……同一个用户总是可以选择碟形或有线电视吗?如果是这样的话,为什么不把这两者都作为项目的参考呢?不需要动态检测。您可能想了解MEF()