如何从字符串创建 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);
我正在使用 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);