I would appreciate it if someone would explain to me how .NET references work when a .dll is compiled.
I have two .dll-s, my primary application.dll references my services.dll. The purpose of the services.dll is to provide a decoupled layer for communication with third party services so that changes to the integrations do not affect the application directly.
To achieve this decoupling I have inherited the services primary object exposing and using the new object in the main application:
public class CustomClient : ServiceClient_v1
{
public CustomClient(binding, address) : base (binding, address) {}
}
However, I am finding that when ServiceClient_v1 gets updated to ServiceClient_v2 and I try and just update the services.dll then my application.dll blows up saying:
Could not load type "ServiceClient_v1" from assembly services.dll
So it is still hanging onto a direct reference to that other object that I am trying to hide. I assume this is by design and simply something to do with compilation that I do not understand.
Is there a way to achieve what I want? And why is my method not working?
Since you're deriving CustomClient from ServiceClient_v1 in your application.dll, it will only work with the older version of your services.dll that contains the definition of ServiceClient_v1. As Lasse Vågsæther Karlsen pointed out, the ServiceClient_v1 class becomes part of the public declaration of CustomClient.
I believe you would benefit from applying Dependency Injection and the Liskov substitution principle in your application.
In order to achieve your goal of a truly interchangeable services.dll you need to refactor your architecture removing the dependency of services.dll from application.dll, it should be the other way around.
Define an Interface for your ServiceClient type. Both CustomClient and ServiceClient_v1 must implement this interface.
When you later update the code to use ServiceClient_v2, it should also implement the interface, which will be unchanged. Now everything continues to work without needing to re-complile the application.dll project.
Alternatively, don't rename the ServiceClient type in services.dll when moving from v1 to v2. This is what version control systems like git or SVN or are for.
Related
How to version abstractions in .Net when applying Dependency Inversion in a high code-reuse environment
I am interested in shifting toward using Dependency Inversion in .Net, but have come across something that puzzles me.
I don’t believe it is tied to a particular method or provider of DIP, but more a fundamental issue that perhaps others have solved. The issue I'm solving for is best laid out step-by-step as scenario below.
Assumption / Restriction
A considerable assumption or restriction to put out there up front, is that my development team has stuck with a rule of keeping our deployed assemblies to one and only one Assembly Version, specifically version “1.0.0.0”.
Thus far, we have not supported having more than this one Assembly Version of any given assembly we’ve developed deployed on a server for the sake of simplicity. This may be limiting, and there may be many good reasons to move away from this, but never the less, it is currently a rule we work with. So with this practice in mind, continue below.
Scenario
You have an IDoStuff interface contained in an abstraction assembly
Stuff.Abstractions.dll with 2 methods.
You compile component A.dll
with a class explicitly implementing IDoStuff with 2 methods.
You move A.dll to production use, Assembly Version 1.0.0.0, Assembly File
version 1.0.0.0.
You move Interface.dll to prod, Assembly Version
1.0.0.0, Assembly File version 1.0.0.0.
Everything works fine. Time passes by.
You add another method (“DoMoreStuff” for example) to the IDoStuff interface so that a different Component B can call it.
(Keeping Interface Segregation OO principle in mind, let’s say the DoMoreStuff method makes sense to be in this relatively small IDoStuff interface.)
You now have IDoStuff with 3 methods in Stuff.Abstractions.dll, and you’ve built Component B to use the new 3rd method.
You move Stuff.Abstractions.dll to production use (upgrade it), Assembly Version 1.0.0.0, Assembly File Version 1.0.0.1.
(note that the file version is incremented, but the assembly version and therefore the strong name stays the same)
You move B.dll to production use, Assembly Version 1.0.0.0, Assembly File version 1.0.0.17.
You don’t do a thing to A.dll. You figure there are no changes needed at this time.
Now you call code that attempts to execute A.dll on the same production server where it had been working before. At runtime the Dependency Inversion framework resolves the IDoStuff interface to a class inside A.dll and tries to create it.
Problem is that class in A.dll implemented the now extinct 2-method IDoStuff interface. As one might expect, you will get an exception like this one:
Method ‘DoMoreStuff’ in type ‘the IDoStuff Class inside A.dll’ from assembly ‘strong name of assembly A.dll’ does not have an implementation.
I am presented with two ways that I can think of to deal with this scenario when I’d have to add a method to an existing interface:
1) Update every functionality-providing assembly that uses Stuff.Abstractions.dll to have an implementation of the new ‘DoMoreStuff’ method.
This seems like doing things the hard way, but in a brute-force way would painfully work.
2) Bend the Assumption / Restriction stated above and start allowing more than one Assembly Version to exist (at least for abstraction definition assemblies).
This would be a bit different, and make for a few more assemblies on our servers, but it should allow for the following end state:
A.dll depends on stuff.abstractions.dll, Assembly Version 1.0.0.0, Assembly File Version 1.0.0.22 (AFV doesn’t matter other than identifying the build)
B.dll depends on stuff.abstractions.dll, Assembly Version 1.0.0.1, Assembly File Version 1.0.0.23 (AFV doesn’t matter other than identifying the build)
Both happily able to execute on the same server.
If both versions of stuff.abstractions.dll are installed on the server, then everything should get along fine. A.dll should not need to be altered either. Whenever it needs mods next, you’d have the option to implement a stub and upgrade the interface, or do nothing. Perhaps it would be better to keep it down to the 2 methods it had access to in the first place if it only ever needed them.
As a side benefit, we’d know that anything referencing stuff.abstractions.dll, version 1.0.0.0 only has access to the 2 interface methods, whereas users of 1.0.0.1 have access to 3 methods.
Is there a better way or an accepted deployment pattern for versioning abstractions?
Are there better ways to deal with versioning abstractions if you’re trying to implement a Dependency Inversion scheme in .Net?
Where you have one monolithic application, it seems simple since it’s all contained – just update the interface users and implementers.
The particular scenario I’m trying to solve for is a high code-reuse environment where you have lots of components that depend on lots of components. Dependency Inversion will really help break things up and make Unit Testing feel a lot less like System Testing (due to layers of tight coupling).
Part of the problem may be that you're depending directly on interfaces which were designed with a broader purpose in mind. You can mitigate the problem by having your classes depend on abstractions which were created for them.
If you define interfaces as needed to represent the dependencies of your classes rather than depending on external interfaces, you'll never have to worry about implementing interface members that you don't need.
Suppose I'm writing a class that involves an order shipment, and I realize that I'm going to need to validate the address. I might have a library or a service that performs such validations. But I wouldn't necessarily want to just inject that interface right into my class, because now my class has an outward-facing dependency. If that interface grows, I'm potentially violating the Interface Segregation Principle by depending on an interface I don't use.
Instead, I might stop and write an interface:
public interface IAddressValidator
{
ValidationResult ValidateAddress(Address address);
}
I inject that interface into my class and keep writing my class, deferring writing an implementation until later.
Then it comes time to implement that class, and that's when I can bring in my other service which was designed with a broader intent than just to service this one class, and adapt it to my interface.
public class MyOtherServiceAddressValidator : IAddressValidator
{
private readonly IOtherServiceInterface _otherService;
public MyOtherServiceAddressValidator(IOtherServiceInterface otherService)
{
_otherService = otherService;
}
public ValidationResult ValidateAddress(Address address)
{
// adapt my address to whatever input the other service
// requires, and adapt the response to whatever I want
// to return.
}
}
IAddressValidator exists because I defined it to do what I need for my class, so I never have to worry about having to implement interface members that I don't need. There won't ever be any.
There's always the option to version the interfaces; e.g., if there is
public interface IDoStuff
{
void GoFirst();
void GoSecond();
}
There could then be
public interface IDoStuffV2 : IDoStuff
{
void GoThird();
}
Then ComponentA can reference IDoStuff and ComponentB can be written against IDoStuffV2. Some people frown on interface inheritance, but I don't see any other way to easily version interfaces.
I have a Winform application where I would like to implement some sort of an interface for the customer, so parts of the code is changeable by customer later on if they need to. I believe my approach is wrong, because I get an error in Visual Studio after recompiling my Winform application. The error is "Argument type MyClass is not assignable to parameter type MyClass", but I'm still able to recompile it. I'm worried this would break later on...
This is how I have implemented it until now:
In my winform application I have created an abstract class with a virtual method.
I'm "releasing" an open source project dll assembly for the customer where this abstract class is implemented and the method is calling the base method in the abstract class. If customer would like to change the method, they simply implement it themselves.
This open source project is then referenced and implemented in my winform application.
When customer would like to change the method they implement the method, recompile the dll and replace the new dll with the one I distributed with my assembly.
My winform application has it's own strong name, and the open source project has it's own strong name.
However, when I recompile my Winform application after having referenced the open source project, i get this error: "Argument type MyClass is not assignable to parameter type MyClass". I can still recompile the project. But I'm concerned the implementation has some serious flaws and will break later on. Especially also since I have implemented WyBuild where I will distribute updates for the Winform application.
I need to provide a way for the customer to change some methods in the application without having access to all the source code. How can this be achieved if my implementation is wrong, what is your suggestion?
Thanks.
I'd say that approach itself is a bad way to do it. To me, this sound very error prone, and you state yourself that you have a bad feeling about it. If so, then really don't do it this way.
There sure is a couple of other solution thinkable, but given your descriptions I might do it as follows, which would stay your your original intention.
Have a look at Microsoft's Managed Extensibility Framework (MEF), which could help you in several ways.
Simply put, it would work like this:
You define the interface that the custumer has to implement.
The client then creates an assembly that implements exactly that interface and puts it a location that is monitored by MEF
MEF loads the assembly automatically (no need to reinvent the wheel)
MEF gives you a lot of control over how you want it to work. Like, like should it allow loading only or multiple assemblies that implement that interface at the same time, or should only look for plugins only at the start of the application or monitor the plugin location during the full life-time of it.
Also by doing it this way you get rid of the custom solution you are assembling here and instead use a mature framework that provides a standadized way to do it. Just have look at some tutorials on the net, it is really easy to get into.
We have code that is called by an external framework, ARDEN. Short of a comment (easily overlooked), how can I effectively notify developers of tie in's to this framework? Specifically, a tie in couples the CLASS, NAMESPACE and METHOD to said framework.
namespace MyCompany//changing namespace for this class is NOT SAFE
{
public class MyClass//changing class name is NOT SAFE
{
[TiedToArdenAttribute]//maybe an attribute?
public void MethodCalledByArden() {}//adding params, changing name is NOT SAFE
public void NotCalledByArden() {}//changing this method signature, name, params is OK
}
}
Under normal circumstances, for example when I change the name of MyClass in an assembly via visual studio I can't compile without fixing the references to said class. If the namespace, classname or method name changes...there should be a warning that says "best fix Arden to deal with this change". I considered an Error, but since there's no way to verify Arden is fixed I don't believe that will work.
Is there a way to achieve a similar result for this external framework?
I think whatever you do can be undone by other developers - they can rename class, remove comments, remove attributes.
Try to move this class to separate library instead. And in your project add reference to compiled assembly. That will make class name fixed in your project.
If others are using the code, it is best to talk in terms of contracts and not class instances via interfaces. By allowing the consumer to use an Interface will dictate the primary changes such as property changes...but things like internal class name changes will not affect a consumer. Plus you can version your classes, while working on a new class, the old class could still be used by the consumer until the factory internally releases it, without the consumer knowing that V2 of the class is being used.
I've recently become a heavy user of Autofac's OwnedInstances feature. For example, I use it to provide a factory for creating a Unit of Work for my database, which means my classes which depend on the UnitOfWork factory are asking for objects of type :
Func<Owned<IUnitOfWork>>
This is incredibly useful--great for keeping IDisposable out of my interfaces--but it comes with a price: since Owned<> is part of the Autofac assembly, I have to reference Autofac in each of my projects that knows about Owned<>, and put "using Autofac.Features.OwnedInstances" in every code file.
Func<> has the great benefit of being built into the .NET framework, so I have no doubts that it's fine to use Func as a universal factory wrapper. But Owned<> is in the Autofac assembly, and every time I use it I'm creating a hard reference to Autofac (even when my only reference to Autofac is an Owned<> type in an interface method argument).
My question is: is this a bad thing? Will this start to bite me back in some way that I'm not yet taking into account? Sometimes I'll have a project which is referenced by many other projects, and so naturally I need to keep its dependencies as close as possible to zero; am I doing evil by passing a Func<Owned<IUnitOfWork>> (which is effectively a database transaction provider) into methods in these interfaces (which would otherwise be autofac-agnostic)?
Perhaps if Owned<> was a built-in .NET type, this whole dilemma would go away? (Should I even hold my breath for that to happen?)
I agree with #steinar, I would consider Autofac as yet another 3rd party dll that supports your project. Your system depends on it, why should you restrict yourself from referencing it? I would be more conserned if ILifetimeScope or IComponentContext were sprinkled around your code.
That said, I feel your consern. After all, a DI container should work behind the scenes and not "spill" into the code. But we could easily create a wrapper and an interface to hide even the Owned<T>. Consider the following interface and implementation:
public interface IOwned<out T> : IDisposable
{
T Value { get; }
}
public class OwnedWrapper<T> : Disposable, IOwned<T>
{
private readonly Owned<T> _ownedValue;
public OwnedWrapper(Owned<T> ownedValue)
{
_ownedValue = ownedValue;
}
public T Value { get { return _ownedValue.Value; } }
protected override void Dispose(bool disposing)
{
if (disposing)
_ownedValue.Dispose();
}
}
The registration could be done, either using a registration source or a builder, e.g. like this:
var cb = new ContainerBuilder();
cb.RegisterGeneric(typeof (OwnedWrapper<>)).As(typeof (IOwned<>)).ExternallyOwned();
cb.RegisterType<SomeService>();
var c = cb.Build();
You can now resolve as usual:
using (var myOwned = c.Resolve<IOwned<SomeService>>())
{
var service = myOwned.Value;
}
You could place this interface in a common namespace in your system for easy inclusion.
Both the Owned<T> and OwnedWrapper<T> are now hidden from your code, only IOwned<T> is exposed. Should requirements change and you need to replace Autofac with another DI container there's a lot less friction with this approach.
I would say that it's fine to reference a well defined set of core 3rd party DLLs in every project of an "enterprise application" solution (or any application that needs flexibility). I see nothing wrong with having a dependency on at least the following in every project that needs it:
A logging framework (e.g. log4net)
Some IoC container (e.g. Autofac)
The fact that these aren't part of the core .NET framework shouldn't stop us from using them as liberally.
The only possible negatives I can see are relatively minor compared to the possible benefits:
This may make the application harder to understand for the average programmer
You could have version compatibility problems in the future which you wouldn't encounter if you were just using the .NET framework
There is an obvious but minor overhead with adding all of these references to every solution
Perhaps if Owned<> was a built-in .NET
type, this whole dilemma would go
away? (Should I even hold my breath
for that to happen?)
It will become a built-in .NET type: ExportLifeTimeContext<T>. Despite the name, this class isn't really bound to the .NET ExportFactory<T>. The constructor simply takes a value, and an Action to invoke when the lifetime of that value is disposed.
For now, it is only available in Silverlight though. For the regular .NET framework you'll have to wait until .NET 4.x (or whatever the next version after 4.0 will be).
I don't think referencing the Autofac assembly is the real problem - I consider things like Owned appearing in application code a 'code smell'. Application code shouldn't care about what DI framework is being used and having Owned in your code now creates a hard dependency on Autofac. All DI related code should be cleanly contained in a set of configuration classes (Modules in the Autofac world).
I have a solution with 2 projects.
One, Raven, is a simple base that provides data for the second project, PPather, to do stuff with. The second project depends on the first to compile so to build it, I add a reference to Raven. All works well so far.
Now I want Raven to launch PPather. But it can't see the PPather naemspace so I can't. All efforts to resolve this lead to circular reference errors.
Anyone know how I can get Raven to see the namespace of the PPather project that depends on it?
You can't - there is no way to reference assemblies in a circular manner like you want to do. Most likely you have not properly designed these assemblies if you need to create a circular reference.
Your first assembly is a dependency so there should not be any code in there that knows about anything other than its dependencies. Once your assemblies become "smart" and begin to have knowledge of anything outside their own dependencies you will begin to have serious maintenance and scalability headaches. I would look into reorganizing your code in such a manner that you do not need to create the circular reference.
As Andrew says, you can't and it doesn't make much sense that you'd want to.
Basically, do one of the following:
Merge the assemblies; if they really inter-depend tightly, then they really should not be separate in the first place.
Re-design the assemblies so that they do not directly depend on each other in both directions; for instance, make assembly A depend on an interface defined in assembly C, and have assembly B implement this interface (both depend on C).
There is a ton of stuff you can do to achieve this if you are not willing to combine them into one component. All basically strive to either invert one of the dependencies or to create a third component on which both depend.
It seems that Raven is the starting point, so one possible solution is to create a base class or interface in the PPather component which reflects the feature set that PPather seeks in Raven. Raven can then implement this base class and then include a "this"-pointer when instantiating/invoking PPather. PPather will expect a pointer to the base class (or interface) in his own assembly, and therefore will never "know of" Raven except through his own abstraction. Therefore, the circular dependency will be broken (by means of dependency injection).
It is fortunate that you can not add circular references - because they cause maintenance nightmares.
You want Raven to launch PPather? Is PPather as console/windows application? Use Process.Start to do that (and store the location of PPather in the registry somewhere).
Alternatively create interfaces for the classes that you need out of PPather - and make the classes in PPather implement those interfaces.
interface IPPatherInterface // Inside of Raven.
{
void Foo();
}
class PPatherClass : IPPatherInterface // Inside of PPather
{
// ...
}
class SomeRavenClass // Static maybe? Inside of Raven
{
void SupplyPPatherClass(IPPatherInterface item) { ... }
}
You now have a way for PPather to supply that interface's implementation to Raven.
Branch out the calsses in raven that Panther needs to use from raven to a different assembly, and have both panther and Raven reference them.
Although to be honest if Raven needs to run panther then i think your design is a bit Off. you should break off your code into something more manageable.