我在.net 4.5中开发了一个Web应用程序,现在客户问我一些应用程序模块的定制(例如发票的不同实现)。 我的问题是,我可以“拦截”我的客户负载定制组装并为一般客户加载不同的组件吗?
我可以通过反思来做到这一点吗?
答案 0 :(得分:1)
关键的想法是按照零件易于更换的方式设计软件。您应该将解决方案分成多个项目,以便快速交换接口的不同实现。
此外,还有一个名为Dependency Injection的东西,它基本上意味着您可以根据需要在运行时或使用配置文件中注入不同的实现。为了便于使用,已经为您准备了很好的框架,比如Ninject或Unity。
应用程序需要具有可靠的架构来支持这些可能性。也许如果您提供了有关系统的更多信息,我可能会更具体,但我相信对依赖注入进行一些研究会给你一个良好的开端。
答案 1 :(得分:0)
是的,你可以。您可以从文件加载程序集,如下所示
var asmbly = System.Reflection.Assembly.LoadFrom(path);
然后使用Reflection加载类型。
有几种方法可以实现这种可插拔性。一种方法是提取“模块”的接口并再次编写“模块客户端”接口,将具体实现与“客户端”代码分离。然后,在运行时查看assempbly内部,加载实现所述接口的类型并注入“模块客户端”。
我在这里粘贴了一些我编写的代码作为概念证明,可以实现“模块”的运行时加载(这是MVC 3):
// "Module User" was decoupled from "module", by coding it against module's interface:
public class CustomerController : Controller
{
private ICustomerRepository _customerRepository;
// dependency injection constructor
public CustomerController(
...
ICustomerRepository customerRepository,
...)
{
_customerRepository = customerRepository;
}
public ActionResult Details(Nullable<Guid> id)
{
Customer c = _customerRepository.GetByKey(id.Value.ToString());
...
}
...
}
在运行时:
// I first load the assembly
System.Reflection.Assembly dal = System.Reflection.Assembly.LoadFrom(System.IO.Path.Combine(pBinPath, pDALAssemblyName));
// I then look for types implementing ICustomerRepository
var addressRepositoryContract = typeof(QSysCamperCore.Domain.IAddressRepository);
var addressRepositoryImplementation = dal.GetTypes()
.First(p => addressRepositoryContract.IsAssignableFrom(p));
...
请注意,这种类型的编程需要更多权限 - 我已经在此代码上“生锈”了几年,但我记得信任级别的问题,当然,必须考虑文件系统访问。
有一些框架可以帮助这种应用程序风格。这又是几年之久,但在Microsoft的模式和实践网站上曾经有所谓的“复合应用程序块”,它是两个框架的基础--Smart Cliet Softweare Factory及其Web等价物 - Web客户端软件工厂。它们站起来有点重,但为这种模块化(复合)应用提供了可怕的骨架。