I have a .NET assembly that I’m building and I want only a few classes and methods to be visible to the end user. I’m creating the assembly with a library class project in framework 4.5 with Visual Studio 2015. The assembly will provide a control console of sorts to manage some interrelated backend services and applications. Most of the work will happen within the assembly, and will be invisible to the end user. Most of the classes in the assembly’s namespace will be internal and so invisible to the end user; but the assembly will provide a few public classes and methods that the end user can interact with. The way I envision it, the assembly will provide a public static class where the end user will pass in the parameters needed by the assembly, and then return an object that the end user can utilize. For example, here is a pseudocode template of what that public static class might look conceptually like.
我有一个我正在构建的.NET程序集,我只希望最终用户可以看到几个类和方法。我正在使用Visual Studio 2015在框架4.5中使用库类项目创建程序集。程序集将提供各种控制台来管理一些相互关联的后端服务和应用程序。大多数工作将在程序集中进行,并且对最终用户是不可见的。程序集命名空间中的大多数类都是内部的,对最终用户来说是不可见的;但程序集将提供一些最终用户可以与之交互的公共类和方法。我设想它的方式,程序集将提供一个公共静态类,最终用户将传递程序集所需的参数,然后返回最终用户可以使用的对象。例如,这是一个伪代码模板,表示公共静态类在概念上看起来像什么。
public static class ControlClientStarter
{
public static ISrvcManagerConsole GetSrvcManagerConsole(/*. all the parameters . */)
{
// Some code that parses the parameters . . .
ISrvc_Controller accountController = new AccountSrvc_Controller( /*. . . */ );
ISrvc_Controller contractController = new ContractSrvc_Controller( /*. . . */ );
ISrvc_Controller imageController = new ImageSrvc_Controller( /*. . . */ );
ICatalogApp_Controller calatlogController = new CatalogApp_Controller( /*. . . */ );
IPortal_Controller portalController = new PortalSrvc_Controller( /*. . . */ );
ISrvcManagerConsole srvcMngrConsole = new SrvceManagerConsole(
accountController,
contractController,
imageController,
calatlogController,
portalController);
return srvcMngrConsole;
}
}
The code above demonstrates that the assembly .dll provides a public static class called ControlClientStarter which has one public static method called GetSrvcManagerConsole() ( . . .). That static method accepts several parameters, and then based on those parameters and various logic, creates objects that implement the ISrvc_Controller interface as well as other objects that implement other interfaces. Those objects are injected into the constructor of the srvcMngrConsole object and returns that to the end user.
上面的代码演示了程序集.dll提供了一个名为ControlClientStarter的公共静态类,它有一个名为GetSrvcManagerConsole()(...)的公共静态方法。该静态方法接受多个参数,然后基于这些参数和各种逻辑,创建实现ISrvc_Controller接口的对象以及实现其他接口的其他对象。这些对象被注入到srvcMngrConsole对象的构造函数中,并将其返回给最终用户。
The end user would access the control console with something conceptually similar to this,
最终用户将使用与此类似的概念访问控制台,
ISrvcManagerConsole clientMngrConsole = ControlClientStarter.GetSrvcManagerConsole( /*. . . */ );
clientMngrConsole.DoThis( /*. . . */ );
clientMngrConsole.StopThis( /*. . . */ );
clientMngrConsole.GetThat( /*. . . */ );
clientMngrConsole.PublishThat( /*. . . */ );
The inside of the control console might look something abstractly like this pseudocode where the arguments passed into the SrvcManagerConsole get saved to interface implementing fields within the srvcMngrConsole object,
控制台的内部可能看起来像这个伪代码,其中传递给SrvcManagerConsole的参数被保存到srvcMngrConsole对象中的接口实现字段,
internal class SrvcManagerConsole : ISrvcManagerConsole
{
ISrvc_Controller accountController ;
ISrvc_Controller contractController ;
ISrvc_Controller imageController ;
ICatalogApp_Controller calatlogController;
IPortal_Controller portalController ;
internal SrvcManagerConsole(
ISrvc_Controller accountController,
ISrvc_Controller contractController,
ISrvc_Controller imageController,
ICatalogApp_Controller calatlogController,
IPortal_Controller portalController)
{
this.accountController = accountController;
this.contractController = contractController;
this.imageController = imageController;
this.calatlogController = calatlogController;
this.portalController = portalController;
}
public void DoThis( /*. . . */ )
{ /*. . . */ }
public void StopThis( /*. . . */ )
{ /*. . . */ }
public void GetThat( /*. . . */ )
{ /*. . . */ }
public void PublishThat( /*. . . */ )
{ /*. . . */ }
// private and-or internal methods and properties . . .
}
As you can see, I’m using a constructor dependency injection to avoid tight-coupling; but there is a problem with that. What if in the future I want to add a MapPublishApp_Controller, a VideoSrvc_Controller, and so on?
如您所见,我正在使用构造函数依赖注入来避免紧耦合;但是有一个问题。如果将来我想添加MapPublishApp_Controller,VideoSrvc_Controller等,该怎么办?
If I add them to the constructor after the first release, then other code that already uses this assembly will also have to change. If I add another SrvceManagerConsole constructor with additional parameters that take the new controllers, then I won’t be breaking previous code, but the constructor parameters will start to get too numerous. Also, depending on the parameters that the end user sends to the GetSrvcManagerConsole() method of the ControlClientStarter class, I might not want to use all of the controllers. It would be much better if I could have methods that add the controllers to the fields. The challenge is that I wouldn’t want the end user to be able to access those fields. I only want the assembly to instantiate the controller classes and assign the hidden fields. If I give those those assignment methods in the SrvceManagerConsole class internal access modifiers, then the GetSrvcManagerConsole() method can’t see them because it is public.
如果我在第一个版本之后将它们添加到构造函数中,那么已经使用此程序集的其他代码也必须更改。如果我添加另一个SrvceManagerConsole构造函数以及带有新控制器的其他参数,那么我将不会破坏以前的代码,但构造函数参数将开始变得太多。此外,根据最终用户发送到ControlClientStarter类的GetSrvcManagerConsole()方法的参数,我可能不想使用所有控制器。如果我可以有将控制器添加到字段的方法会好得多。挑战在于我不希望最终用户能够访问这些字段。我只希望程序集实例化控制器类并分配隐藏字段。如果我在SrvceManagerConsole类内部访问修饰符中提供那些赋值方法,那么GetSrvcManagerConsole()方法无法看到它们,因为它是公共的。
Note the access modifiers on the interfaces. The only one that is public is the one that is implemented by the SrvcManagerConsole class. The rest are internal because they should not be accessible to the end user.
请注意接口上的访问修饰符。唯一公开的是由SrvcManagerConsole类实现的。其余的是内部的,因为最终用户不应该访问它们。
internal interface ISrvc_Controller { /*. . . */ }
internal interface ICatalogApp_Controller { /*. . . */ }
internal interface IPortal_Controller { /*. . . */ }
public interface ISrvcManagerConsole
{
void DoThis( /*. . . */ );
void StopThis( /*. . . */ );
void GetThat( /*. . . */ );
void PublishThat( /*. . . */ );
}
Those methods above like PublishThat() will use the fields that got set to the objects injected into the constructor. The end-user programmer that uses my assembly will never see those interface implementing instances. The clientMngrConsole object created by the end user programmer will use those internal objects without the programmer even knowing how they’re used.
像PublishThat()这样的上述方法将使用设置为注入构造函数的对象的字段。使用我的程序集的最终用户程序员永远不会看到那些实现实例的接口。最终用户程序员创建的clientMngrConsole对象将使用这些内部对象,而程序员甚至不知道它们是如何被使用的。
The classes that implement interfaces with internal access modifiers would abstractly be something like this,
实现具有内部访问修饰符的接口的类将抽象地类似于此,
class AccountSrvc_Controller : ISrvc_Controller { /*. . . */ }
class ContractSrvc_Controller : ISrvc_Controller { /*. . . */ }
class ImageSrvc_Controller : ISrvc_Controller { /*. . . */ }
class CatalogApp_Controller : ICatalogApp_Controller { /*. . . */ }
class PortalSrvc_Controller : IPortal_Controller { /*. . . */ }
There might be more controller classes in the future, maybe not. I’ve been unable to figure out how to assign the controller classes to back end fields in a way that those fields will be inaccessible to the end user while maintaining some level of loose coupling incase the implementation of those controllers needs to change in the future. I have discovered, however, that if the other methods and properties are stated in the ISrvceManagerConsole interface, and that interface is set with a public modifier, those methods and properties in the SrvceManagerConsole class that implements that interface can also be set as public and successfully accessed despite the SrvceManagerConsole class itself being set as "internal." I tried property setter injection, but C# (wisely) does not support a property with an interface backend (because that wouldn’t make any sense). Another possibility is to have the SrvceManagerConsole constructor take one parameter which wraps all the other interface instances in a dictionary perhaps. I haven’t tried that yet. I can’t be the first person to have confronted this. There must be a common solution that I’ve been unable to locate. I know that the industry standard is to use IoC containers for what I’m doing above, but that’s not going to be done here. I’ve never tried an architecture like this before. I know that this is probably not the best architecture; but for now it doesn’t have to be exactly according to some overly complex architecture. I’m going for an adequate design as I’m learning more about this.
未来可能会有更多的控制器类,也许不是。我一直无法弄清楚如何将控制器类分配给后端字段,使得最终用户无法访问这些字段,同时保持一定程度的松耦合,这些控制器的实现需要在将来进行更改。但是,我发现,如果在ISrvceManagerConsole接口中声明了其他方法和属性,并且该接口是使用public修饰符设置的,那么实现该接口的SrvceManagerConsole类中的那些方法和属性也可以设置为public并成功尽管SrvceManagerConsole类本身被设置为“内部”,但仍可访问。我尝试了属性setter注入,但C#(明智地)不支持具有接口后端的属性(因为这没有任何意义)。另一种可能性是让SrvceManagerConsole构造函数接受一个参数,该参数可能包装字典中的所有其他接口实例。我还没有尝试过。我不能成为第一个遇到这种情况的人。必须有一个我无法找到的共同解决方案。我知道行业标准是使用IoC容器来完成我上面所做的事情,但这不会在这里完成。我以前从未尝试过这样的架构。我知道这可能不是最好的架构;但是现在它并不一定完全符合一些过于复杂的架构。我正在寻找一个适当的设计,因为我正在学习更多这方面的知识。
Edit # 1, why the Builder pattern doesn’t work here
编辑#1,为什么Builder模式在这里不起作用
Suppose I try to avoid the constructor anti-pattern by using a builder pattern like the pseudocode below.
假设我尝试通过使用类似下面的伪代码的构建器模式来避免构造函数反模式。
Imagine that the SrvcManagerConsole looks like this:
想象一下,SrvcManagerConsole看起来像这样:
internal class SrvcManagerConsole : ISrvcManagerConsole
{
internal ISrvc_Controller accountController;
internal SrvcManagerConsole() { }
internal void AddAccountController(ISrvc_Controller accountController)
{
this.accountController = accountController;
}
}
Imagine I change the ControlClientStarter to something like this:
想象一下,我将ControlClientStarter更改为以下内容:
public static class ControlClientStarter
{
public static ISrvcManagerConsole GetSrvcManagerConsole(/*. all the parameters . */)
{
Federated_ControlBuilder fedBuilder = new Federated_ControlBuilder();
ISrvcManagerConsole srvcMngrConsole = fedBuilder.GetSrvcManagerConsole();
return srvcMngrConsole;
}
}
And then I implement the Federated_ControlBuilder like this:
然后我像这样实现Federated_ControlBuilder:
internal class Federated_ControlBuilder : IControl_Builder
{
internal ISrvcManagerConsole srvcMngrConsole;
internal Federated_ControlBuilder()
{
srvcMngrConsole = new SrvcManagerConsole();
}
public void InjectAccountController(ISrvc_Controller accountController)
{
// The srvcMngrConsole object can not see the InjectAccountController method.
// srvcMngrConsole.
}
internal ISrvcManagerConsole GetSrvcManagerConsole()
{
return srvcMngrConsole;
}
}
The InjectAccountController(…) method of the Federated_ControlBuilder class can’t see the AddAccountController(…) method of the SrvcManagerConsole class because it is internal.
Federated_ControlBuilder类的InjectAccountController(...)方法无法看到SrvcManagerConsole类的AddAccountController(...)方法,因为它是内部的。
The sticking point of my question is not how to avoid a constructor anti- pattern in and of itself; but rather the challenge is to avoid the anti-pattern while making certain classes and methods in an assembly inaccessible to the end user programmer, hence, the use of the word “internal” title of the question, “How to implement Setter Dependency Injection on internal Access Modifiers.”
我的问题的关键不在于如何避免构造函数反模式本身;但更挑战的是避免反模式,同时使最终用户程序员无法访问程序集中的某些类和方法,因此,使用“内部”标题的问题,“如何实现Setter Dependency Injection on内部访问修饰符。“
If it were merely a question of avoiding a constructor anti-pattern, I could have made the fields of the SrvcManagerConsole public and added to them directly through the GetSrvcManagerConsole(…) method of the ControlClientStarter class.
如果它只是避免构造函数反模式的问题,我可以公开SrvcManagerConsole的字段并直接通过ControlClientStarter类的GetSrvcManagerConsole(...)方法添加到它们中。
3 个解决方案
#1
0
I would recommend using the builder pattern to avoid the telescoping constructor anti-pattern. Then, your code need only add setters to implement new features, and you leave your constructor empty.
我建议使用构建器模式来避免伸缩构造器反模式。然后,您的代码只需添加setter来实现新功能,并将构造函数留空。
#2
0
I don’t know if this is a good solution or not, but it seems to be working for what I was trying to accomplish. To recap, I wanted an assembly where the inner workings would be inaccessible by having their classes’ access modifiers set to internal, but would provide some public classes that would provide a sort of console user interface functionality to those who would use the assembly. The problem was that the if the public classes had back end fields that were set with internal access modifiers, the other internal classes could not inject values into those fields. My solution to this was to create two namespaces in the assembly. One namespace would have all the classes set to the internal access modifier. Those are the classes for the inner logic of the assembly. The second namespace would have its classes set to public. It would have a using statement that referenced the first namespace. Those public classes in the second name space can then request objects from classes in the first namespace. The classes in the second name space then wrap those objects and provide the wrapper to the end user.
我不知道这是否是一个好的解决方案,但它似乎正在努力实现我想要实现的目标。回顾一下,我想要一个程序集,通过将类的访问修饰符设置为内部,可以无法访问内部工作,但是会提供一些公共类,它们将为那些使用程序集的人提供一种控制台用户界面功能。问题是,如果公共类具有使用内部访问修饰符设置的后端字段,则其他内部类无法将值注入这些字段。我的解决方案是在程序集中创建两个名称空间。一个名称空间将所有类设置为内部访问修饰符。这些是程序集内部逻辑的类。第二个命名空间将其类设置为public。它将有一个引用第一个命名空间的using语句。然后,第二个名称空间中的那些公共类可以从第一个名称空间中的类请求对象。然后,第二个名称空间中的类将这些对象包装起来,并为最终用户提供包装器。
Here is an example from the assembly’s first namespace:
这是程序集的第一个命名空间中的一个示例:
// This is the first namespace with all classes set to internal.
namespace ControlClient
{
internal class ClientStarter
{
internal IArcManagerConsole mngrConsole;
internal ClientStarter() { }
internal IManagerConsole GetSrvcManagerConsole(/*. all the parameters . */)
{
ConsoleBuildDirector cnslBldDirector = new ConsoleBuildDirector();
IConsoleBuilder fedBuilder = new Federated_ConsoleBuilder();
cnslBldDirector.DirectBuildingConsole(fedBuilder);
mngrConsole = fedBuilder.GetSrvcManagerConsole();
return mngrConsole;
}
}
}
Here is an example from the assembly’s second namespace with public classes accessible by the end programmer.
下面是程序集的第二个命名空间中的示例,其中公共类可由最终程序员访问。
using ControlClient; // referencing the first name space
// This is the second namespace with public classes.
namespace ClientUserInterface
{
/// <summary>
/// SrvcManagerConsole wraps the mngrConsole.
/// They both implement the IManagerConsole interface.
/// </summary>
public class SrvcManagerConsole
{
IManagerConsole srvcManager;
public SrvcManagerConsole()
{
// this.srvcManager = srvcManager;
ClientStarter ccs = new ClientStarter();
this.srvcManager = ccs.GetSrvcManagerConsole();
}
// The DoThis() method of this wrapper class will
// call the DoThis() method of the object from the
// first namespace that implements the same
// interface. The end user can't see the
// srvcManager object.
public void DoThis()
{
srvcManager.DoThis();
}
}
}
Here is an example from the end user’s project.
以下是最终用户项目的示例。
using ClientUserInterface; // This is the second namespace
using ControlClient; // This is the first namespace (all classes set to internal).
namespace EndUser
{
class EndUser
{
public EndUser()
{
// The end user can access public classes from the assembly's
// second namespace, ArcClientUserInterface as seen below.
SrvcManagerConsole sMC = new SrvcManagerConsole();
sMC.DoThis();
// Trying to access anything here from the assembly's
// first namespace, ArcControlClient will fail.
// Now, all the inner workings of the assembly are undetectable.
}
}
}
The end user will add the assembly to his project references and then can try to use both namespaces; but only the second namespace would provide items that can be accessed. Only the classes in that second namespace (including the wrapper) can be used by the end user. The object received from the first namespace and manipulated by the wrapper is inaccessible to the end user. Items from the first assembly are then inaccessible to the end user’s project and invisible because they are all set to the internal access modifier. The end user manipulates the wrapper and the wrapper in turn manipulates the object received from the first namespace. So, the way to implement setter dependency injection on internal access modifiers is to have all the classes in one namespace set to internal that will participate in the setter dependency injection. Then provide a second namespace that uses the object from the first namespace, wraps it, and then provides the public classes to the end-user programmers. Any feed back and advice will be appreciated. Thanks in advance.
最终用户将程序集添加到项目引用中,然后可以尝试使用两个名称空间;但只有第二个命名空间才能提供可以访问的项目。最终用户只能使用第二个命名空间中的类(包括包装器)。从第一个命名空间接收并由包装器操纵的对象对最终用户是不可访问的。然后,第一个程序集中的项目对最终用户的项目是不可访问的,并且不可见,因为它们都设置为内部访问修饰符。最终用户操纵包装器,包装器依次操纵从第一个命名空间接收的对象。因此,在内部访问修饰符上实现setter依赖项注入的方法是将一个名称空间中的所有类设置为内部参与setter依赖项注入。然后提供第二个命名空间,该命名空间使用第一个命名空间中的对象,将其包装,然后将公共类提供给最终用户程序员。任何反馈和建议将不胜感激。提前致谢。
#3
0
You could use InternalVisibleToAttribute to allow integration code to manipulate internal setter but not other front end assemblies.
您可以使用InternalVisibleToAttribute来允许集成代码操作内部setter而不是其他前端程序集。
Moreover, I developed an dependency injection not based on constructor injection nor member injection, but a full custom injection by specifying lambda expression to tell how to create an infrastructure instance.
此外,我开发了一个不依赖于构造函数注入和成员注入的依赖注入,而是通过指定lambda表达式来告知如何创建基础结构实例的完全自定义注入。
You may found a part of the solution here : Puresharp API .net 4.5.2+
您可以在此处找到解决方案的一部分:Puresharp API .net 4.5.2+
#1
0
I would recommend using the builder pattern to avoid the telescoping constructor anti-pattern. Then, your code need only add setters to implement new features, and you leave your constructor empty.
我建议使用构建器模式来避免伸缩构造器反模式。然后,您的代码只需添加setter来实现新功能,并将构造函数留空。
#2
0
I don’t know if this is a good solution or not, but it seems to be working for what I was trying to accomplish. To recap, I wanted an assembly where the inner workings would be inaccessible by having their classes’ access modifiers set to internal, but would provide some public classes that would provide a sort of console user interface functionality to those who would use the assembly. The problem was that the if the public classes had back end fields that were set with internal access modifiers, the other internal classes could not inject values into those fields. My solution to this was to create two namespaces in the assembly. One namespace would have all the classes set to the internal access modifier. Those are the classes for the inner logic of the assembly. The second namespace would have its classes set to public. It would have a using statement that referenced the first namespace. Those public classes in the second name space can then request objects from classes in the first namespace. The classes in the second name space then wrap those objects and provide the wrapper to the end user.
我不知道这是否是一个好的解决方案,但它似乎正在努力实现我想要实现的目标。回顾一下,我想要一个程序集,通过将类的访问修饰符设置为内部,可以无法访问内部工作,但是会提供一些公共类,它们将为那些使用程序集的人提供一种控制台用户界面功能。问题是,如果公共类具有使用内部访问修饰符设置的后端字段,则其他内部类无法将值注入这些字段。我的解决方案是在程序集中创建两个名称空间。一个名称空间将所有类设置为内部访问修饰符。这些是程序集内部逻辑的类。第二个命名空间将其类设置为public。它将有一个引用第一个命名空间的using语句。然后,第二个名称空间中的那些公共类可以从第一个名称空间中的类请求对象。然后,第二个名称空间中的类将这些对象包装起来,并为最终用户提供包装器。
Here is an example from the assembly’s first namespace:
这是程序集的第一个命名空间中的一个示例:
// This is the first namespace with all classes set to internal.
namespace ControlClient
{
internal class ClientStarter
{
internal IArcManagerConsole mngrConsole;
internal ClientStarter() { }
internal IManagerConsole GetSrvcManagerConsole(/*. all the parameters . */)
{
ConsoleBuildDirector cnslBldDirector = new ConsoleBuildDirector();
IConsoleBuilder fedBuilder = new Federated_ConsoleBuilder();
cnslBldDirector.DirectBuildingConsole(fedBuilder);
mngrConsole = fedBuilder.GetSrvcManagerConsole();
return mngrConsole;
}
}
}
Here is an example from the assembly’s second namespace with public classes accessible by the end programmer.
下面是程序集的第二个命名空间中的示例,其中公共类可由最终程序员访问。
using ControlClient; // referencing the first name space
// This is the second namespace with public classes.
namespace ClientUserInterface
{
/// <summary>
/// SrvcManagerConsole wraps the mngrConsole.
/// They both implement the IManagerConsole interface.
/// </summary>
public class SrvcManagerConsole
{
IManagerConsole srvcManager;
public SrvcManagerConsole()
{
// this.srvcManager = srvcManager;
ClientStarter ccs = new ClientStarter();
this.srvcManager = ccs.GetSrvcManagerConsole();
}
// The DoThis() method of this wrapper class will
// call the DoThis() method of the object from the
// first namespace that implements the same
// interface. The end user can't see the
// srvcManager object.
public void DoThis()
{
srvcManager.DoThis();
}
}
}
Here is an example from the end user’s project.
以下是最终用户项目的示例。
using ClientUserInterface; // This is the second namespace
using ControlClient; // This is the first namespace (all classes set to internal).
namespace EndUser
{
class EndUser
{
public EndUser()
{
// The end user can access public classes from the assembly's
// second namespace, ArcClientUserInterface as seen below.
SrvcManagerConsole sMC = new SrvcManagerConsole();
sMC.DoThis();
// Trying to access anything here from the assembly's
// first namespace, ArcControlClient will fail.
// Now, all the inner workings of the assembly are undetectable.
}
}
}
The end user will add the assembly to his project references and then can try to use both namespaces; but only the second namespace would provide items that can be accessed. Only the classes in that second namespace (including the wrapper) can be used by the end user. The object received from the first namespace and manipulated by the wrapper is inaccessible to the end user. Items from the first assembly are then inaccessible to the end user’s project and invisible because they are all set to the internal access modifier. The end user manipulates the wrapper and the wrapper in turn manipulates the object received from the first namespace. So, the way to implement setter dependency injection on internal access modifiers is to have all the classes in one namespace set to internal that will participate in the setter dependency injection. Then provide a second namespace that uses the object from the first namespace, wraps it, and then provides the public classes to the end-user programmers. Any feed back and advice will be appreciated. Thanks in advance.
最终用户将程序集添加到项目引用中,然后可以尝试使用两个名称空间;但只有第二个命名空间才能提供可以访问的项目。最终用户只能使用第二个命名空间中的类(包括包装器)。从第一个命名空间接收并由包装器操纵的对象对最终用户是不可访问的。然后,第一个程序集中的项目对最终用户的项目是不可访问的,并且不可见,因为它们都设置为内部访问修饰符。最终用户操纵包装器,包装器依次操纵从第一个命名空间接收的对象。因此,在内部访问修饰符上实现setter依赖项注入的方法是将一个名称空间中的所有类设置为内部参与setter依赖项注入。然后提供第二个命名空间,该命名空间使用第一个命名空间中的对象,将其包装,然后将公共类提供给最终用户程序员。任何反馈和建议将不胜感激。提前致谢。
#3
0
You could use InternalVisibleToAttribute to allow integration code to manipulate internal setter but not other front end assemblies.
您可以使用InternalVisibleToAttribute来允许集成代码操作内部setter而不是其他前端程序集。
Moreover, I developed an dependency injection not based on constructor injection nor member injection, but a full custom injection by specifying lambda expression to tell how to create an infrastructure instance.
此外,我开发了一个不依赖于构造函数注入和成员注入的依赖注入,而是通过指定lambda表达式来告知如何创建基础结构实例的完全自定义注入。
You may found a part of the solution here : Puresharp API .net 4.5.2+
您可以在此处找到解决方案的一部分:Puresharp API .net 4.5.2+