简体   繁体   English

查找类以按名称实例化而无需命名空间或程序集? (。净)

[英]Find class to instantiate by name without namespace or assembly? (.NET)

I'd like to instantiate a class by name (a string) without specifying a namespace or assembly. 我想通过名称(字符串)实例化一个类而不指定名称空间或程序集。 Like this (Unity syntax): 像这样(Unity语法):

var processor = container.Resolve<IProcessor>("SpecialProcessor");

would instantiate the first IProcessor it finds called SpecialProcessor. 将实例化它找到的第一个IProcessor,称为​​SpecialProcessor。 Maybe 也许

MyNamespace.SpecialProcessor

I'd like to avoid having to create an entry in a config every time somebody adds a new processor. 我想避免每次有人添加新处理器时都必须在配置中创建条目。 I'm fine with having an entry for all candidate assemblies though. 我可以为所有候选程序集添加一个条目。

Can I use an IoC container for something like this or should I roll my own? 我可以使用IoC容器进行此类操作还是应该自己滚动?

Here's a function that does something very similar to what you want. 这是一个功能,与您想要的功能非常相似。 You can modify it to filter based on a specific class name pretty easily. 您可以很容易地对其进行修改以根据特定的类名进行过滤。

These functions have references to a few utilities we use for logging and exception handling. 这些函数引用了一些我们用于日志记录和异常处理的实用程序。 You'll need to replace them with whatever you normally do in these situations. 在这种情况下,您需要用通常的操作替换它们。

    public static T FindAndCreate<T>(bool localOnly, bool exportedOnly)
    {
        Type[] types = FindAssignableClasses(typeof(T), localOnly, exportedOnly, false);
        if (types.Length == 0)
        {
            return default(T);
        }
        if (types.Length != 1)
        {
            Log.Warn(typeof(ReflectionUtil),
                     "FindAndCreate found {0} instances of {1} whereas only 1 was expected.  Using {2}.  {3}",
                     types.Length,
                     typeof(T).FullName,
                     types[0].FullName,
                     String.Join("\r\n  ", Array.ConvertAll<Type, String>(types, GetFullName)));
        }
        try
        {
            return (T)Activator.CreateInstance(types[0]);
        }
        catch (Exception ex)
        {
            throw ExceptionUtil.Rethrow(ex,
                                        "Unable to create instance of {0} found for interface {1}.",
                                        types[0].FullName,
                                        typeof(T).FullName);
        }
    }

    public static Type[] FindAssignableClasses(Type assignable, bool localOnly, bool exportedOnly, bool loadDll)
    {
        var list = new List<Type>();
        string localDirectoryName = Path.GetDirectoryName(typeof(ReflectionUtil).Assembly.CodeBase);

        if (loadDll && !_loadedAllDlls)
        {
            foreach (string dllPath in Directory.GetFiles(localDirectoryName.Substring(6), "*.dll"))
            {
                try
                {
                    Assembly.LoadFrom(dllPath);
                }
                catch
                {
                    // ignore
                }
            }
            _loadedAllDlls = true;
        }

        foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
        {
            try
            {
                if (localOnly && Path.GetDirectoryName(asm.CodeBase) != localDirectoryName)
                {
                    continue;
                }

                Type[] typesInAssembly;
                try
                {
                    typesInAssembly = exportedOnly ? asm.GetExportedTypes() : asm.GetTypes();
                }
                catch
                {
                    continue;
                }

                foreach (Type t in typesInAssembly)
                {
                    try
                    {
                        if (assignable.IsAssignableFrom(t) && assignable != t)
                        {
                            list.Add(t);
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Debug(
                            typeof(ReflectionUtil),
                            String.Format(
                                "Error searching for types assignable to type {0} searching assembly {1} testing {2}{3}",
                                assignable.FullName,
                                asm.FullName,
                                t.FullName,
                                FlattenReflectionTypeLoadException(ex)),
                            ex);
                    }
                }
            }
            catch (Exception ex)
            {
                // ignore dynamic module error, no way to check for this condition first
                // http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/7b02223aefc6afba/c8f5bd05cc8b24b0
                if (!(ex is NotSupportedException && ex.Message.Contains("not supported in a dynamic")))
                {
                    Log.Debug(
                        typeof(ReflectionUtil),
                        String.Format(
                            "Error searching for types assignable to type {0} searching assembly {1} from {2}{3}",
                            assignable.FullName,
                            asm.FullName,
                            asm.CodeBase,
                            FlattenReflectionTypeLoadException(ex)),
                        ex);
                }
            }
        }

        return list.ToArray();
    }

It sounds like you have a plugin architecture and you want to allow other components to provide implementations of IProcessor without having to update some master config file. 听起来您具有插件体系结构,并且您希望允许其他组件提供IProcessor实现,而不必更新某些主配置文件。 If that's the case, then I think you are best suited by using MEF (managed extensibility framework) ( Website ). 如果是这样,那么我认为您最适​​合使用MEF(托管可扩展性框架)( 网站 )。

This is a framework designed to allow such behavior. 这是一个旨在允许此类行为的框架。 Once you establish a catalog of assemblies to load components from, importing the collection of IProcessor instances is as easy as the following 一旦建立了要从中加载组件的程序集目录,导入IProcessor实例的集合就很容易,如下所示

var processors = container.GetExportedValues<IProcessor>();

There are many tutorials online for MEF that should get you started. 在线上有许多MEF教程可以帮助您入门。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用.net core中的反射按名称查找类的命名空间? - How to find namespace of class by its name using reflection in .net core? 如何实例化给定类名称和基本命名空间的对象 - How to instantiate objects given a Class name and a base Namespace 实例化没有公共构造函数的.NET类 - Instantiate .NET class without public constructor 如何在程序集中找到实例化类X对象的所有方法? - How to find all methods in assembly that instantiate object of class X? 如何使用带有C#/ .NET的Reflection实例化程序集中的类? - How to instantiate the class in an assembly using Reflection with C#/.NET? .net中相同的类名称和程序集名称 - Same class name and assembly name in .net 程序集名称和默认命名空间 - Assembly Name and Default Namespace C#找不到类-找不到类型或名称空间名称“ GradeBook”(您是否缺少using指令或程序集引用?) - C# cannot find class - The type or namespace name 'GradeBook' could not be found (are you missing a using directive or an assembly reference?) 获取没有名称空间的枚举或类的字符串名称? - Get the string name of an enumeration or class without namespace? C#/ .NET如何从类名中找到包含的命名空间 - C#/.NET How do I find the containing namespace from a class name
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM