Resolving Unity Dependencies without a Unity.MVC - c#

I have two projects that use the following Unity logic:
container.RegisterType<IUnitOfWork, MyDbContext>(
new HierarchicalLifetimeManager(),
new InjectionFactory(
c => new MyDbContext(configurationService.MySqlConnectionString)
)
);
container.RegisterType<DbContext, MyDbContext>(
new HierarchicalLifetimeManager()
);
The first project is a web application that utilises the Unity.MVC4 package so has a bespoke DependencyResolver doing some of the work - this works perfectly.
The second is a non-web application so uses a normal Unity package instance but errors when a call is made that uses MyDbContext. The exception is
System.Data.Entity.Core.MetadataException: Schema specified is not
valid. Errors: EntityDataModel.MyProject.ssdl(2,2) : error 0152: The
Entity Framework provider type
'System.Data.Entity.SqlServer.SqlProviderServices,
EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089' for the 'System.Data.SqlClient'
ADO.NET provider could not be loaded. Make sure the provider assembly
is available to the running application. See
http://go.microsoft.com/fwlink/?LinkId=260882 for more information.
I've setup both projects to call the same service, which is in a separate project, in an attempt to isolate the source of the problem to the second project's Unity logic. I should also note I'm using Entity Framework 6 as the ORM.
My question is what Unity code do I need to get the second project to work, or is there some app.config entry I can add to reference the EF assemblies?
Update:
After some additional work I noticed that if I reference the DbContext assemblies:
EntityFramework
EntityFramework.SqlServer
in the second projects the problem disappears. I want to avoid referencing these assemblies because my client projects shouldn't have any knowledge of the ORM.
I've also tried updating the connection string so I'm manually specifying the ORM project's assembly (where my EDMX file is) as mentioned in this StackOverflow question but that hasn't made any difference.
metadata=res://nameOfDll/Model.csdl|res://nameOfDll/Model.ssdl|res://nameOfDll/Model.msl

You're doing it in the right way.
With DI you can remove dependencies from your application. So that you can get a "Repository agnostic" application. And you have effectively done it. At least on the projects that 'declare' the dependencies.
However, when the application has to run, you need to specify the concrete objects which will be used for the "declared" abstract dependencies (interface, abstract class) is required.
You do this by registering the types which object will be used for each abstract dependency. In you sample, when a IUnitOfWork or a DbContext, an instance of MyDbContext is provided.
So the projects that 'declare' the dependencies are completely independent of a particular implementation.
However, when you register the dependent types, you're loosing that independence.
Let's see it with an example:
If I say "I'm thirsty, I need to drink but I don't mind what I drink", I'm dependent on any drink, not on a particular one. But If I say "When I'm thirsty I want to drink coke" I'm dependent on coke.
The first part is the abstract definition of the dependency: "any drink" (like the abstract IUnitOfWork or DbContext). And the second part is the concrete dependency: "coke" (like MyDbContext).
So, I'm independent from coke as long as I don't specify that's what I want to drink. But once I say it, I'm dependent.
Perhaps what you're looking for is a way to change the repository at runtime. You can do it: don't register the dependencies in your code, because you need to make a reference to the project with the chosen concrete types. Do it in an external configuration (i.e. a file), so that you can compile your project without reference to the dependencies, and provide the required assemblies at runtime.
NOTE: When I say "declare" I mean using any of the patterns for injecting dependencies, like constructor injection (most advisabke) or any other injection pattern (property dependencies).

Related

PostSharp dependency sprawl

I defined a custom attribute 'attribute' in a library 'Lib' that I use to annotate a method 'method' in a project 'Service'. However, when unit testing 'method' (in a distinct unit test project that holds a reference to 'Service' to depend on it), I am getting :
System.TypeLoadException: Could not load type 'attribute' from
assembly 'Lib'.
Why?
I tried adding a updated the dependency on 'Lib' of the unit test project, which solves the exception. However, I do not understand why it has to be updated, I thought the reference to 'attribute' could be encapsulated in 'Service' without requiring projects depending on 'Service' to upgrade 'Lib' version as well
Asked in a more abstract and generic way: is it possible to annotate the outermost layer of a code base (say, the HTTP api facade of a service), or will PostSharp annotations only work if the consumer of an API depends of the attribute class itself.
I am fairly new to C#, so I am not sure if this is a PostSharp feature, a c# dependency management feature, or a mix of both. Seems dependencies are not transitively resolved, but still, I don't expect the unit test project to directly depend on 'attribute', even though it calls a method annotated with it

Roslyn analyzer/codefix dependencies

I'm trying to write an analyzer with codefix and I'm unsure on how I can
Add a required base class to the consumer project.
Preferred method would be to have it available at build time only (so generated)
Add the required dependency that this base class has to the consumer project so that compilation of the code fix does not fail. Maybe it's possible to check during analyze phase if that project has that dependency already installed?
The base class is needed by the generated code from the code fix and inherently the dependency of a 3rd party nuget.

Factory pattern where concrete classes are on separate DLLs

I wrote a dlls that connect to some 3rd party API, each DLL has the methods: SignIn,Upload,Download,SignOut.
My manager asked me to implement a factory pattern because in future I will write more dlls to other APIs that has the same methods signuture.
For now I have:
DLL 1: OneDrive
It has a class with methods: SignIn,Upload,Download,SignOut.
So if I want to use it I'm adding reference to this DLL and then any app can use this DLL.
DLL 2: DropBox
It has also class with methods: SignIn,Upload,Download,SignOut.
My question: How do I implement the factory method design pattern in this secnario?
What I did: I created another DLL("The new DLL") this DLL would contain the "FactoryClass", the problem is that the creator in this dll should return a type of "OneDrive" or "DropBox" that means I should add refernce to the first two dlls ("OneDrive" and "DropBox").
But, The classes "OneDrive" and "DropBox" should implement some abstrct class whithin the new dll that means I should add refernce to the new dll.
but it's not possible because it's circular dependency (Visual studio error)
In order to eliminate the circular dependencies, you must keep the dependencies in the direction of your main assembly.
This is in partly solved by an interface (or abstract class) declared in this central assembly, but there is the additional problem of instantiating the concrete implementations without directly referencing the dependencies.
This can be solved by allowing your factory to keep a registry of available implementations. You can find an example of a simple factory with registration in this other stack overflow question

Why I need to add same reference when this reference had been added from another project

Here is a Question, Supposed that I have two projects:
Application(console)
DataAccess(class library).
In DataAccess project, there is a DataContext class inherited from DbContext
public class DataContext : DbContext {...}
In Application project, I has added DataAccess reference, and in main method I added following statement:
using (var context = new DataContext ()){...}
but Resharper show
The type DbContext is defined in an assembly not referenced.
Why do I need to add the same assembly again?
Why can't I get DbContext definition from DataAccess.dll?
(DataAccess project has added EntityFramwork.dll through NuGet)
Edit 1: When a type inherited another type(ex: DataContext inherited from DbContext), why compiler didn't include the definition of DbContext in the same dll, so in another project, we just only need to add reference to child type's dll ?
Because your class library (the .dll) doesn't 'contain' its dependent assemblies. So your executing assembly needs to have references to the dependent assemblies too if it wants to use your class library.
(It's a bit the same as with config files, they aren't embedded either, so even if you have for example a connectionstring defined in the config file of the class library, you still need to define it into your start-up application too.)
If you really want to embed libraries into a single dll you can take a look at ILMerge but it's recommended to just include all the libraries you need in your start-up application.
Another good one (that I can recommend) is Costura.Fody. You just need to install it through NuGet, no configuration required whatsoever and when you build your application the next time, it will embed everything into your class library.
Because the type you want to reach is on that assembly.
Because you want to be able to define a variable on that type. It is like:
DataContext dbContext = new DataContext();
dbContext.Users.ToList();
this is what you want to do in presentation layer using by DAL. But the problem is you still using entity framework.
Lets create a function on service layer which has dependency on EntityFramework.
List<User> GetUsers()
{
DataContext dbContext = new DataContext();
dbContext.Users.ToList();
}
And now we can simply call this service and function without adding Entity Framework reference. That's because; In presentation layer, we have nothing to do with entity framework right now. We are just calling a function. But in your case you are just using entity framework with the Context from another project. That's why your code needs EF refence and mine doesnt.
Thanx

Universal Apps with IoC: Dependency management/isolation

I'm a huge fan of using Unity for .NET applications to keep code module and dependencies "manageable" in large code-bases. I've used it for years with .NET by dropping assemblies into the main program's program directory and re-configuring an IoC configuration file (usually the .exe.config file), injecting new behaviour into a program without needing to re-compile the main program.
However, I have started my foray into writing universal apps for Windows Store and more importantly, Windows IoT - however because these apps are "packaged up" during compilation, I'm finding it difficult to understand how best to continue doing this.
One possible option would be to compile the "modules" (PCL/Universal class libraries) and include them (and their dependencies) as "Content" files within the Universal app, then use reflection to load types from these assemblies during the start-up of the program via reflection.
Another option would be to include all modules and their dependencies into the main program's project references before compilation but using "poor man's dependency injection to hard code the registrations and resolutions", but this feels really wrong to me - I'd ideally like to keep the separation of dependencies if at all possible?
Any ideas...?
PS. I'm not tied to Unity in any way, if there is another IoC library that does it better on this platform then fine - but Unity is what I already know and love!
I do this using Castle Windsor. You can probably use the same approach with Unity:
Limit references only to when an assembly needs a type defined in
another assembly
Define a class (or classes depending on how you want to organize) for IoC configuration in each assembly by implementing IWindsorInstaller and configure DI using the fluent API inside the implemented Install method.
Define a container instance inside your app root
At application start, use reflection to find all types implementing
IWindsorInstaller in the bin folder and run their Install method,
passing in the container instance
This way you can keep your dependencies separate, and you don't have to worry about adding extra references or adding .dlls as content files.

Categories