Ways of loading external dll and injecting conditionally multiple implementations using autofac - c#-4.0

i have an interface called say IMyHook which has some implementation in an external project(dll). i use this interface in my businesslogic classes and on my application startup i inject external implementation of this interface using Autofac.
my interface
public interface IMyHook {
public void MyHookMethod();
}
my business logic class
public class myBusinessLogic{
// implementation injected by autofac
public IMyHook Hook {set;get;}
public void MyBusinessLogicMethod (flag){
if(Hook !=null){
Hook.MyHookMethod();
}
else{
// other code
}
}
}
auto face properties injection
var hoodAssemblyPath = "C:\\hook.dll";
builder.RegisterAssemblyTypes(hoodAssemblyPath).
AsImplementedInterfaces().PropertiesAutowired();
this works all fine but now issue is that my external dll (hook.dll) can have more then one implementations of IMyHook. And i want to decide which implementation to load in my MyBusinessLogicMethod method using the input paramameter flag. e.g
if (flag ==1)
then load implementation 1
else if (flag == 2)
then load implememtation 2
etc
i can do this using Reflections (and a custom attribute in my external classes representing each value of flag) by loading assembly and then the appropriate class using custom attribute on it.
But my question is;
is this the right way loading external dll on each method call using reflection etc or are there any other ways of doing this? using autofac or anything else?
with all this i want to let users of my application to inject their code in my application for some of the functionality. so external dll or implementations will basically be written by my users and then my application will just load and execute the methods.

Registering all the dependencies using AsImplementedInterfaces().PropertiesAutowired(); could be quite heavy and you may encounter problem on complex scenario. Furthermore, you won't be able to customize the way the registration is made for each registration (controlling lifetimescope, etc.)
I would recommend to register module that your users have to write inside these assemblies. Then load them using RegisterAssemblyModules.
if (flag ==1) then load implementation 1 else if (flag == 2) then load implememtation 2 etc
How would you decide which implementation to use ? implementation1 means implementation coming from Hook1.dll ?
A common way to do this is to use Named and Keyed Services and/or Component Metadata
If you can't ask your users to implement module you can use something like this :
builder.RegisterAssemblyTypes(hoodAssemblyPath)
.AsImplementedInterfaces()
.PropertiesAutowired()
.WithMetadata("source", "hook1");
and then
IFoo foo = container.Resolve<IEnumerable<Lazy<IFoo, String>>>()
.First(f => f.Metadata["source"] == "hook1")
.Value
If you do it this way consider using typed metadata.

Related

Jhipster override entity (keep existant + add behaviour)

I like the jhipster entity generator.
I often get to change my model and regen all entities.
I wish to keep the generated stuff and override for my needs.
On angular side, it is quite easy to create a new service extending the default entity service to do my stuff.
On java side, it is more complicated.
For example, I override src/main/java/xxx/web/rest/xxxResource.java with src/main/java/xxx/web/rest/xxxOverrideResource.java
I have to comment #RestController in xxxResource.java. I tried to give it a different bundle name from the overrided class but it is not sufficient : #RestController("xxxResource")
In xxxOverrideResource.java, I have to change all #xxxMapping() to different paths
In xxxOverrideResource.java, I have to change all method names
This allow me to keep the CRUD UI and API, and overload it using another MappingPath.
Some code to make it more visual. Here is the generated xxxResource.java
/**
* REST controller for managing WorldCommand.
*/
// Commented to prevent bean dupplicated error.
// #RestController
#RequestMapping("/api")
public class WorldCommandResource {
private final WorldCommandService worldCommandService;
public WorldCommandResource(WorldCommandService worldCommandService) {
this.worldCommandService = worldCommandService;
}
#PutMapping("/world-commands")
#Timed
public ResponseEntity<WorldCommand> updateWorldCommand(#Valid #RequestBody WorldCommand worldCommand)
throws URISyntaxException {
log.debug("REST request to update WorldCommand : {}", worldCommand);
...
}
Here is my overloaded version : xxxOverrideResource.java
/**
* REST controller for managing WorldCommand.
*/
#RestController("WorldCommandOverrideResource")
#RequestMapping("/api")
public class WorldCommandOverrideResource extends WorldCommandResource {
private final WorldCommandOverrideService worldCommandService;
public WorldCommandOverrideResource(WorldCommandOverrideService worldCommandService) {
super(worldCommandService);
log.warn("USING WorldCommandOResource");
this.worldCommandService = worldCommandService;
}
#PutMapping("/world-commands-override")
#Timed
public ResponseEntity<WorldCommand> updateWorldCommandOverride(#Valid #RequestBody WorldCommand worldCommand)
throws URISyntaxException {
throw new RuntimeException("WorldCommand updating not allowed");
}
With the xxxResource overrided, it is easy to override the xxxService and xxxRepository by constructor injection.
I feel like I am over thinking it. As it is not an external component but code from a generator, maybe the aim is to use the tool to write less code and then do the changes you need.
Also, I fear this overriding architecture will prevent me from creating abstract controller if needed.
Do you think keeping the original generated code is a good pratice or I should just make my changes in the generated class and be carefull when regenerating an entity ?
Do you know a better way to override a Spring controller ?
Your approach looks like the side-by-side approach described here: https://www.youtube.com/watch?v=9WVpwIUEty0
I often found that the generated REST API is only useful for managing data in a backoffice and I usually write a complete separate API with different endpoints, authorizations and DTOs that is consumed by mobile or end-users. So I don't see much value in overriding REST controllers, after all they are supposed to be quite thin with as little business logic as possible.
You must also consider how long you want to keep this compatibility with generated code. As your app grows in complexity you might want to refactor your code and organize it around feature packages rather than by technical packages (repository, rest controllers, services, ...). For many reasons, sooner or later the way the generated code is setup will get in your way, so I would not put too much effort into this compatibility goal that has no real business value especially when you know that the yearly released major version may break it because of changes in the generator itself or more likely because of changes in underlying frameworks.

Buiding Orchard Module - Telling Autofac to use different implementations

As I exposed here, I would like to be able to query freely on the index without Orchard building the query for me.
I built a module, and inserted a copy of the SearchController, adding a new route...
To override default Orchard behavior concerning the query, I had to create new implementations of : ISearchService, IIndexManager, ISearchBuilder, IIndexProvider.
There are minor modifications from their default implementations, but they are needed.
That works as expected, but it currently override the default search too.
This is because I used the same interfaces and autofac takes my implementations.
I would like to be able to leave the default implementation untouched (at url /Search), and add my implementation at url (/LuceneSearch for example)
I suppose I must tell Autofac to use my implementations only for my controller by creating a class that inherits the autofac Module class.
Here is my problem : I don't know how to tell Autofac to use by default the Orchard Implementation, and just for my controller, use my implementation....
Another possibility is to create new interfaces, but it seems to me not really beautiful...
Can someone help me ? :)
Metadata feature will help you here. Also you have to register your implementations with PreserveExistingDefaults() modifier to preserve orchard's implementations by default.
Update:
Orchard registers all dependencies from Autofac's IModule implementation and from Orchard's IDependency one. All magic happen in Orchard's ShellContainerFactory class. Since ISearchService inherits from IDependency your implementation is registered by Orchard which overwrites default one.
You have two ways here:
Introduce your own empty interface IMySearchService which inherits from ISearchService. Implement and use it in your code where you need your implementation. Orchard will handle all registrations for your.
Orchard registers all IDependency implementations with "Feature" Metadata in ShellContainerFactory.RegisterType method. You can read this metadata in your code and choose your implementation (see link to wiki above). Feature class contains all necessary information about your module.
Hope this will help you.
A simpler method without dabbling with the intricacies of Autofac would be to use an IEnumerable<IInterface> variable in your controller/driver at url "/LuceneSearch" to hold all implementations of IInterface and choose which to consume.
For example, in order to consume your implementation of IIndexManager, you would put the following in your controller or driver
public class MyCustomPartDriver : ContentPartDriver<MyCustomPart> {
private readonly IEnumerable<IIndexManager> _indexManagers;
public MyCustomPartDriver(IEnumerable<IIndexManager> indexManagers) {
_indexManagers = indexManager;
}
protected override DriverResult Display(MyCustomPart part, string displayType, dynamic shapeHelper) {
//Use your implementation of IIndexManager
var indexManager = _indexManagers.First(im => im is MyCustomIndexManager);
//Get the ISearchBuilder from your implementation of IIndexManager
var searchBuilder = indexManager.HasIndexProvider() ? indexManager.GetSearchIndexProvider().CreateSearchBuilder("Search") : new NullSearchBuilder();
//perform search on the indexing engine
var contentItemIds = searchBuilder.
.WithField("type", "MyCustomType").Mandatory().ExactMatch()
.Parse("mycustompart-keyword", part.Keyword).Mandatory()
.Search()
.Select(h => h.ContentItemId)
.ToList();
//do stuff with the results returned and return a DriverResult using the ContentShape method. Well, you know the drill.
}
}
If you don't want to have autofac resolve your own implementation by default, then don't implement the public interface.

How do I define a dependancy for use within an attribute using autofac

I have an asp.net mvc application and I am developing a custom attribute to secure some wcf end points inheriting from a CodeAccessSecurityAttribute.
I'm having difficulty finding out how I would use autofac to inject a service dependancy that I can use within this attribute.
[Serializable]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class SecuredResourceAttribute : CodeAccessSecurityAttribute
{
public ISecurityService SecurityService { get; set; }
public SecuredResourceAttribute(SecurityAction action) : base(action)
{
}
public override IPermission CreatePermission()
{
// I need access to the SecurityService here
// SecurityService == null :(
}
}
I have tried from the application start to register for property auto wiring, but this is not working. What's the best way to inject a dependancy into an attribute?
builder.RegisterType<SecuredResourceAttribute>().PropertiesAutowired();
Thanks
The way you are approaching this is not going to pan out for a couple reasons:
Registering an attribute in autofac will do nothing as you're not using autofac to instantiate the attribute.
Attributes are applied before code execution, and thus rely on constant inputs.
You're going to have to use a service location pattern inside your CreatePermission() method to locate the SecurityService, as I am assuming the CreatePermission() call comes after the container is setup (and the constructor does not!)
Keep in mind ServiceLocation will hinder your class testability, as you will have to configure/set-up the service locator for each test.
Please use with caution
You should start your journey into ServiceLocation here but honestly this should make you question your design. Is an attribute best suited for the role you've tasked it? Perhaps you should look into Aspect-Oriented Programming like PostSharp

MEF and Factory Pattern

i am trying to refactor my project to improve testability, therefor i'm introducing an abstract factory.
My application collects data from different sources by using ICrawlers.
These ICrawlers use 3rd party libraries to access different sources, like e.g. twitter.
Example: My TwitterCrawler uses TweetSharp to access twitter data.
My first version strongly coupled the TweetSharp client to the Crawler. Now i abstracted the TweetSharp to a ITwitterClient and a TweetSharpTwitterClient implementation.
Next step is to introduce a ITwitterClientFactory with a DefaultTwitterClientFactory that creates TweetSharpTwitterClients. This should bring me closer to my goal (testability) because i can switch the factory to MockTwitterClientFactory that creates a MockTwitterClient, that delivers some test output.
Now, let me come to my point.
I am using MEF for dependency injection (but i'm rather new to it). What I'm doing is this:
public class TwitterCrawler : CrawlerBase, ICrawler
{
[Import]
public ITwitterClientFactory TwitterClientFactory {get; set;}
public override Process()
{
ITwitterClient twitterClient = TwitterClientFactory.MakeSingletonClient();
// do something with twitterClient
}
}
Whereas my DefaultTwitterClientFactory exports itself to MEF:
[Export(typeof(ITwitterClient))]
public class DefaultTwitterClientFactory: ITwitterClientFactory
{
// implementation of ITwitterClientFactory
// provides methods to create instances of ITwitterClient implementations
}
Now, while this works so far, my question is, how to switch the factory?
How can i create a unit test and use the MockClientFactory instead of the DefaultTwitterClientFactory?
Is my approach good at all? Is it better to manually set the factory that is to be used?
Somewhere something like
... new TwitterCrawler(mockedTwitterClientFactory)
or even
.... new TwitterCrawler(mockedTwitterClient)?
This actually only moves the problem outside of TwitterClient, but still somewhere i have to decide how to construct the ITwitterClient and what factory to use for that purpose.
Should i dive more into the mechanics of MEF (ExportProvider?)
You shouldn't need to use the composer/container in your unit tests - just wire the SUT directly with the Test Doubles.
Something like this:
var sut = new TwitterCrawler();
sut.TwitterClientFactory = new FakeTwitterClientFactory();
However, you should really refactor from Property Injection to Constructor Injection, as the property implies that the dependency is optional.
BTW, your DefaultTwitterClientFactory doesn't export itself, it exports ITwitterClient.

Code Contracts and Auto Generated Files

When I enabled code contracts on my WPF control project I ran into a problem with an auto generated file which was created at compile time (XamlNamespace.GeneratedInternalTypeHelper). Note, the generated file is called GeneratedInternalTypeHelper.g.cs and is not the same as the GeneratedInternalTypeHelper.g.i.cs which there are several obsolete blog posts about.
I'm not exactly sure what its purpose is, but I am assuming it is important for some internal reflection to resolve XAML. The problem is that it does not have code contracts, nor is the code contract system smart enough to recognize it as an auto generated file. This leads to a bunch of errors from the static checker.
I tried searching for a solution to this problem, but it seems like nobody is developing WPF controls and using code contracts. I did come across an interesting attribute, ContractVerificationAttribute, which takes a boolean value to set whether the assembly or class is to be verified. This allows you to decorate a class as not verified. Sadly the GeneratedInternalTypeHelper is regenerated with every compile, so it is not possible to exclude just this one class. The inverse scenario is possible though, decorate the assembly as not verified and then opt in for every class.
To mitigate the obvious hack I wanted to create a test that would at least verify that the exposed classes have code contract verification with a test like the following to ensure that own classes were at least being verified:
[Fact]
public void AllAssemblyTypesAreDecoratedWithContractVerificationTrue()
{
var assembly = typeof(someType).Assembly;
var exposedTypes = assembly.GetTypes().Where(t=>!string.IsNullOrWhiteSpace(t.Namespace) && t.Namespace.StartsWith("MyNamespace") && !t.Name.StartsWith("<>"));
var areAnyNotContractVerified = exposedTypes.Any(t =>
{
var verificationAttribute = t.GetCustomAttributes(typeof(ContractVerificationAttribute), true).OfType<ContractVerificationAttribute>();
return verificationAttribute.Any() && verificationAttribute.First().Value;
});
Assert.False(areAnyNotContractVerified);
}
As you can see it takes all classes in the controls assembly and finds the one from the company namespace which are not also auto generated anonymous types (<>WeirdClassName).
(I also need to exclude Resources and settings, but I hope you get the idea).
I'm not loving the solution since there are ways of avoiding contract verification, but currently it's the best I can come up with. If anyone has a better solution, please let me know.
So you can treat this class exactly like you would treat any other "3rd party" class or library. I'm sure certain assumptions would hold with the interaction with this generated class so at the interaction points, decorate your own code with Contract.Assume(result != null) or similar.
var result = new GennedClass().GetSomeValue();
Contract.Assume(result != null);
What this does is translate into an assertion that is checked at run time, but it allows the static analyzer to reason about the rest of the code that you do control.

Resources