如何从字符串创建 class、注册然后使用 unity 解析

How to create class from string, register and then resolve using unity

我正在使用 C#、WPF、Prism 6.3 并使用 Unity 作为 IoC 容器。

这是我不太明白的一部分,可以澄清一下。

场景:我的应用程序将与多个物理激光器对话。我创建了一个带有 Views/Viewmodels 的 LaserModule 以及 ILaser 接口和 3 个以上品牌特定的激光器 classes (LaserA/B/C)。由于所有激光器都具有相同的功能(Connect、GetReading、Disconnect),我认为制作 ILaser 接口是个好主意,因此它们都必须实现这些方法,但以它们需要的任何方式。

此外,该模块将从 laser.cfg 文件中读取,并且在该文件中它将具有每个激光器的设置,包括激光器的 "Class",我将使用它来实例化正确的激光 class 与.

总体思路是,无论配置文件中有多少激光器,LaserModule 都会创建适当类型的激光器,然后将它们注册到统一容器中,以便应用程序的其他部分可以访问它们。在我的应用程序的其他部分,目标是程序员不需要了解有关特定激光器或特定 class 的任何信息,而只需使用界面即可。这些接口都将存储在一个公共模块中,因此这应该是唯一的依赖项。

这就是我现在所在的位置...它似乎可以正常工作,因为当最后调用 .Greet() 方法时,我看到了我在使用 Activator.CreateInstance 时发出的问候语.

这种方法是否切合实际,还是我完全没有抓住要点?

namespace LaserModule
{
    interface ILaser
    {
        void Greet();
    }
}


namespace LaserModule
{
    class LaserA: ILaser
    {

        private string greeting = "blank";

        public LaserA(string greet)
        {
            this.greeting = greet;
        }

        public void Greet()
        {
            MessageBox.Show("LaserA - " + greeting);
        }
    }
}

public void Initialize()
{

    //Create Laser objects based on what brand of laser is supplied
    String className = ReadLaserClassNameFunc1();
    Type t = Type.GetType("LaserModule." + className, true);
    object t2 = (Activator.CreateInstance(t,"laser 1 greeting"));
    ILaser myLaser1 = (ILaser)t2;

    //Create Laser objects based on what brand of laser is supplied
    className = ReadLaserClassNameFunc2();
    t = Type.GetType("LaserModule." + className, true);
    t2 = (Activator.CreateInstance(t,"laser 2 greeting"));
    ILaser myLaser2 = (ILaser)t2;

    //Create Laser objects based on what brand of laser is supplied
    className = ReadLaserClassNameFunc3();
    t = Type.GetType("LaserModule." + className, true);
    t2 = (Activator.CreateInstance(t,"laser 3 greeting"));
    ILaser myLaser3 = (ILaser)t2;


    _unityContainer.RegisterInstance("Laser1", myLaser1, new ContainerControlledLifetimeManager());
    _unityContainer.RegisterInstance("Laser2", myLaser2, new ContainerControlledLifetimeManager());
    _unityContainer.RegisterInstance("Laser3", myLaser3, new ContainerControlledLifetimeManager());

    ...
    //The following lines would in reality be called from a different assembly.

    ILaser theLaser1 = _unityContainer.Resolve<ILaser>("Laser1");
    ILaser theLaser2 = _unityContainer.Resolve<ILaser>("Laser2");
    ILaser theLaser3 = _unityContainer.Resolve<ILaser>("Laser3");

    theLaser1.Greet();
    theLaser2.Greet();
    theLaser3.Greet();

}

更新: 添加接口和服务...

ILaserService.cs

using System.Collections.Generic;

namespace xxx.Infrastructure.Interfaces
{
    public interface ILaserService
    {
        void CreateLasers();
        List<ILaser> GetLasers();

    }
}

LaserService.cs

using xxx.Infrastructure.Interfaces;
using System;
using System.Collections.Generic;
using System.Windows;

namespace LaserModule
{
    public class LaserService : ILaserService
    {
        readonly List<ILaser> _lasers = new List<ILaser>();

        public LaserService()
        {            
        }

         public void CreateLasers()
        {

            //Create Laser objects based on config file

            string nameSpace= GetType().Namespace;

            string className = "LaserA";
            Type t = Type.GetType(nameSpace + "." + className, true);
            object t2 = (Activator.CreateInstance(t, "laser 1 greeting"));
            _lasers.Add((ILaser)t2);

            className = "LaserB";
            t = Type.GetType(nameSpace + "." + className, true);
            t2 = (Activator.CreateInstance(t, "laser 2 greeting"));
            _lasers.Add((ILaser)t2);

            className = "LaserC";
            t = Type.GetType(nameSpace + "." + className, true);
            t2 = (Activator.CreateInstance(t, "laser 3 greeting"));
            _lasers.Add((ILaser)t2);


        }

        public List<ILaser> GetLasers()
        {
            return _lasers;
        }

    }
}

LaserModule.cs

using Microsoft.Practices.Unity;
using Prism.Modularity;
using Prism.Regions;
using Prism.Unity;
using System.Windows;
using System;
using xxx.Infrastructure.Constants;
using xxx.Infrastructure.Interfaces;
using System.Collections.Generic;

namespace LaserModule
{
    {
    public class LaserModule : IModule
    {
        private readonly IRegionManager _regionManager;
        private readonly IUnityContainer _unityContainer;

        public LaserModule(IRegionManager regionManager, IUnityContainer unityContainer)
        {
            _regionManager = regionManager;
            _unityContainer = unityContainer;
        }

        public void Initialize()
        {

            //Create and register instance of laser service
            _unityContainer.RegisterInstance(typeof(ILaserService), _unityContainer.Resolve<LaserService>(),new ContainerControlledLifetimeManager());

            //Pull instance out of container
            ILaserService myLaserService = _unityContainer.Resolve<ILaserService>();
            myLaserService.CreateLasers();

            List<ILaser> myLasers = myLaserService.GetLasers();

            MessageBox.Show("LaserModule Ref Hash:" + myLasers.GetHashCode().ToString());

            //Connect and display feedback

            bool allOK = true;

            foreach (ILaser _laser in myLasers)
            {
                if (_laser.Connect() == false)
                {
                    allOK = false;
                }
            }

            if (allOK == true)
            {
                _regionManager.RegisterViewWithRegion(RegionNames.RightSideRegion, typeof(Views.LaserModuleUI1));
                _regionManager.RegisterViewWithRegion(RegionNames.RightSideRegion, typeof(Views.LaserModuleUI2));
            }else
            {
                MessageBox.Show("1 or more lasers failed");
            }


        }
    }
}

Bootstrapper.cs InitializeModules()

    protected override void InitializeModules()
    {

        // Initialize Modules
        base.InitializeModules();

        ILaserService myLaserService = Container.Resolve<ILaserService>();

        List<ILaser> myLasers = myLaserService.GetLasers();

        MessageBox.Show("Bootstrap Ref Hash:" + myLasers.GetHashCode().ToString());

    }

所以只有我的 ILaser 和 ILaserService 在我的 Infrastructure 项目中,所以 Shell 和 LaserModule 依赖于 Infrastructure 而不是彼此。当我在 LaserModule 中创建激光器时,以及当它们在引导程序中从容器中拉出并且它们都匹配时,我正在检查哈希码。

引导程序不需要激光(其他模块需要),但为了概念验证,我认为我做事的方式是正确的。有什么见解吗?

为什么不在您的应用程序中使用 ILaserService 来维护激光器?然后你可以解析ILaserSerrvice,然后向它请求你关心的激光。

示例:

ILaser激光=_laserService.GetLaser(Lasers.LaserOne);