I have a public class, MainObject that is in a class library (dll), for this example we will call it BaseLibrary.
I have a higher level class library that references the BaseLibrary to gain access to it's members. We will call this one DeviceLibrary.
I then have a Windows Forms Project, DeviceControl, in which I have added a reference to DeviceLibrary.
If I need to use a MainObject object, how do I do it? I know I can just add a second reference in the DeviceControl project to the BaseLibrary but I am just wondering if there is another way to access it through the DeviceLibrary? I am not sure what the laws of encapsulation dictate here...
You have to add the reference. If you don't then the compiler will complain and tell you to add the reference. Using Reflection hacks should be a very distant second choice, it merely makes your code slow and still doesn't remove the runtime dependency on the DLL.
Any type to which you refer in your code must be part of a directly referenced assembly.
Although usually not practical, you can use the MainObject without directly referring to it by using a System.Object reference instead and using Reflection to call its members. In C# 4.0 you can probably just use the dynamic keyword:
dynamic x = MethodReturningAMainObject();
x.Foo(); //this will be compiled to use reflection to find "Foo"
Aside from using a dynamic or object reference, you can use any exposed base class or interface that applies to MainObject.
If you are able to alter the contents of the library assemblies (i.e. it's your code), then you could either:
Move MainObject into a separate reference assembly and have any of the existing assemblies reference it. This works well if MainObject is not actually dependent on the other contents of BaseLibrary.
Extract an interface from MainObject and place that in a reference library that every other assembly can reference. Then is you code to the interface, you only need a reference to the new reference library.
If you can't alter the contents of the library assemblies, you could resort to writing a wrapper object for MainObject, with it's own interface and extract the interface to a reference library as in option 2.
Disclaimer: This doesn't fully address your question.
Typically in a N-Tier design the "Models" span all layers. Here is one chart that I reference when designing: http://i.msdn.microsoft.com/cc700340.fig01_L(en-us).gif
I'm not sure what your BaseLibrary includes, but it seems like you may have to reference it from your DeviceLibrary.
Related
Hope my title wasn't too confusing ..
I have several projects in my solution, one of which contains only interfaces MyProgram.Contract. My plugins need to implement these interfaces.
In MyProgram.Contract I reference a 3rd party DLL for some types defined in it, such as one called DataValue.
in MyProgram.MyPlugin I reference MyProgram.Contract and implement the interface, and there is no problem with having a property DataValue Value { get; set; }, as defined in the interface. It compiles, and I can set the value of the Value-property from my main application and display it in my databound view in the plugin.
However, if I try to use DataValue in code in my plugin, I get the error "The type aThirdPartyLib.DataValue is defined in an assembly that is not referenced. You must add a reference to assembly aThirdPartyLib .."
This is what I was wanting to avoid. My wish is that the plugins need no other reference than to MyProgram.Contract. Is there a way to achieve this, or do I need to add all the same references in the plugin-projects as in the plugin contract project?
If you use types from that DLL in your Interface definitions, then implementors of those interfaces will also need a reference to that DLL. No way around that, really.
I created a new unit test project to test my NHibernate mappings.
The NHibernate mappings are in a project that also contains EF entities.
In my unit test I only use types that don't even have an indirect reference to the Entity Framework, but still, when I compile the unit test project, I get the following error:
The type 'System.Data.Objects.DataClasses.IEntityWithRelationships' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Data.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
Is there any way to find out, why this reference is needed? I already checked all used classes multiple times and couldn't find anything...
I have the feeling I am missing something here...
You could use a DLL inspection tool (like JustDecompile (freee!), or Reflector) and have a look inside your test-referenced DLLs. You'll spot the one with the Using statement quite quickly, hopefully, and get a clearer picture of what's happening.
As has been said, double-clicking will pull up the error location but only if it's in code you've written, third party DLLs naturally won't play ball.
Good luck :)
You are sure that you don't use types inheriting or implementing any of the types in System.Data.Entity, this could be buried deep in the inheritance chain, like the use of a method returning a object defined in your DAL which either directly implements IEntityWithRelationships or gets the implementation from a base class also defined in your DAL, that would conceal the use of System.Data.Entity from your test assembly when you try to find references as it would show up as being used by an entity in your DAL instead... (Depending on what feature you are using to determine this, I am just guessing something like "Find Usages")
E.g. in your A, B, C example... if say A uses a B3 class that inherits from C2. When searching for usages on C2 you would only find B3 and not A. But because A uses B3 which inherits C2, A requires a reference to C
I would check out Pistachio. It is made to load in a .csproj, then find all the resources in the project and where they are used. Might be worth a shot to find out where that DLL is needed.
You can use http://checkasm.booring.net/ CheckAsm tool. Load all your assemblies that you refer directly in your project and find out which one is using the missing reference. From there you need to ask the provider of that reference why they needed that assembly.
Hope that would help.
The only thing I can think of is... Since you're using NHibernate and EF, I'm guessing your doing some type of POCO implementation. I've seen some stuff on the web about implementing POCO with NHibernate and EF where the base classes you define implement the IEntityWithRelationships interface. If that's the case it would explain it.
You are referencing a library which has a public method or property that either returns a 'System.Data.Objects.DataClasses.IEntityWithRelationships' or takes one as a parameter. Regardless of it you are actually using the method, because it is public your code has to be able to determine the method signatures of all of the methods in the library you're referencing. If the method was internal you wouldn't see the issue.
I assume you tried just double clicking on the error? That will usually go to the actual point of using the unknown type(either a return value/property or inheritance/implementation).
If that didn't work then it must be in compiler magic code(possibly for EF as people have pointed out, or somewhere else). In that case my suggestion would be to add the reference to your test assembly. Then open it in Reflector and look through the compiled MSIL. Since it is giving you a specific interface you could even just go to that interface and ask Reflector for where it is referenced to see where it is in your assembly.
Could it be that one of your classes has the same name as a EF-class? Then it might be VS that is generating Code to apply the interface IEntityWithRelationships to your class to simulate POCO mapping of the classes.
To use POCO entities with a data model, the name of the entity type must be the same as the custom data class, and each property of the entity type must map to a public property of the custom data class. The names of the types and each of the mapped properties must be equivalent.
Source: http://msdn.microsoft.com/en-us/library/dd456853.aspx
It might be unrelated, but I had similar errors a while ago, I cleared out the ASP.NET assembly cache folder and it fixed my problem.
the folder is here
{windows folder}\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files
and it was holding an old version of my assembly
High level: I am trying to build a console app (e.g. ConsoleApp.exe) which can perform some processing on any given DLL which references a certain type defined in ConsoleApp.exe.
I decided, maybe mistakenly, that I would need a companion DLL for ConsoleApp which contained the type or types (e.g. ConsoleClass) which were intended to be referenced by arbirary DLLs. To pull this off, as I don't know of a better way, I have two projects in the ConsoleApp solution, one is a class library (Proving ConsoleApp.dll) and the other is a console application which references the class library project.
At this point, I now am able to copy my ConsoleApp.dll to another relatively unrelated project in a separate solution (e.g. OtherApp.dll), reference it, and write a method which consumes a ConsoleClass instance as a parameter.
Now, in order to arbitrarily process this OtherApp.dll, the ConsoleApp.exe loads that Assembly, instantiates the proper class in that Assembly, and then calls the proper method on that instance. Pertinent lines below hopefully provide context to how I am doing this:
Assembly.LoadFrom(path_to_OtherApp_dll);
...
var x = (dynamic)Activator.CreateInstance(type_inside_OtherApp_dll);
...
var instance = new ConsoleClass();
x.some_method_call(instance);
Ultimately this fails. It seems to be because even though the two projects (ConsoleApp.exe and OtherApp.dll) are referencing the same DLL to define ConsoleClass, the runtime still considers them to be different types.
Any thoughts?
Define the public interface. Put it to its own interface.dll.
Reference interface.dll in your plugin. Let the main class in your plugin.dll implements your interface.
Reference interface.dll in your exe.
Use Assembly.Load() or Assembly.LoadFrom() to load plugin into your exe.
Use CreateInstance() to create instance of your plugin class.
Simply cast created plugin to your interface type.
So you don't need "dynamic" or other complicated things. Just easy, go step by step as I wrote and it will work. Good luck.
Yes, this will happen when ConsoleApp.dll gets loaded twice. Once by the main app, again by a plugin, using its local copy. A type's identity is determined by the assembly it was loaded from.
It isn't that clear to me how that happened. Your first weapon of choice is Fuslogvw.exe, set it up to log all the binds. First thing to do is to doctor the plugin project and set the Copy Local property of the ConsoleApp.dll reference to False so that extra copy isn't there to get accidentally used.
Copying the plugin DLLs to the main app build folder is the never-have-trouble solution, you can load them with Assembly.Load(). Or a subdirectory with a .config file that uses the <probing> element to allow the CLR to find them.
What do you by "runtime is considering them to be of differnt type"? does setup ends with some exception of error? does method in x variable receives something it does not recognize or what?
I just finished watching an episode of Bob Martin at NDC where he said "using" directives in C# at the top of a page are bad because of the tight coupling they create/imply between components.
What way are there to use external .dlls without adding a project reference and a using statement?
I remember V6 used to let you create an object by the string of the ProgId--I'm not sure that's the technique I'm looking for, but it's an example of a language that didn't need a project reference to use a dll.
EDIT: Here is a link to the conference. Sorry I don't have the exact quote or minute in the presenation, I'm going by memory.
I believe Bob Martin is actually referring to early versus late binding.
In .NET late binding is possible through reflection and more specifically the Activator class that allows creation of a type in an external assembly using a filename or assembly name.
Normally, using directives (not the using statement) go hand in hand with directly referencing an external assembly. ie. You add a reference to an assembly and then add using directives to avoid needing to type the full namespace hierarchy when you use the external types.
So if you find your code has a large number of using directives at the top, it is possible that you are referencing many other types directly and so increasing the coupling/dependency of your code on these types.
I would guess this is why Bob is referring to them as bad. The answer to the question "is this actually bad?" is a very subjective and context dependent one.
In general though, de-coupling of components is almost always a good goal to aim for in designing software. This is because it allows you to change parts of your system with minimal impact on the rest of the system. Having read one or two of Bob Martins books, I would expect this is what he is getting at.
It's not the using statement itself that is bad - it's if you get too many of them.
A statement such as using System; is rarely a problem in itself, but if you have lots (I'd say more than 3-6, depending on which ones) in the same code file, it could be an indication of tight coupling.
You could just as well apply a similar rule of thumb to the number of references in a project itself.
The solution to tight coupling is programming to interfaces and Dependency Injection (DI).
The ProgId way of doing things that you can remember from VB was simply COM in action. In essence, you used that ProgId to get a reference to an instance that implemented the desired interface. The downside was that this only worked when the COM object was universally registered. Remember dll hell?
You can still apply the same principle using certain flavors of DI, only that now the interface is a .NET type and not defined in IDL, and you need some sort of DI Container to supply the concrete implementation.
using is just a shortcut to namespaces, they are not references to external files. Therefore, this is just not really making sense.
Anyways, what one can do is have an interface DLL (a DLL with only interfaces), so that you dynamically load and use different assemblies and create types (through reflection) which you can cast to the well-known interfaces. This is the proper way of loosening external references while keeping the benefits of the strongly typed language and early binding.
Have a look at the Assembly and AppDomain classes to load assemblies, and Activator to create type instances by name.
You could use reflection:
// Load the assembly
Assembly assembly = Assembly.LoadFrom(#"c:\path\Tools.dll");
// Select a type
Type type = assembly.GetType("Tools.Utility");
// invoke a method on this type
type.InvokeMember("SomeMethod", BindingFlags.Static, null, null, new object[0]);
You can do what you are referring to through reflection. You can load the assembly at runtime, and reflect through it to get the classes etc. and call them dynamically.
Personally, I wouldn't do this though to avoid coupling. To me that is a bad use of reflection, and I would much rather add it to the project and reference it, unless there is a specific reason why not to do so. Reflection adds overhead to the system, and you don't get the advantage of compile time safety.
In C#, I am developing several Windows Services which have some standard functionality so I have put all this common functionality into a separate referenced utility project.
I have a situation where I need to create instances of business classes which reside in my Windows Service project from the utility project using Activator.CreateInstance.
My utility project is aware of the namespace and the class name for the Type.GetType call but the type is always null and when I think about it, it won’t be able to get the type from the project it’s referenced to, or can it?
In short:
Project A references Utility Project.
Utility Project wants to create class from Project A, its aware of the namespace and class name.
Is there a Design Pattern or an approach that I should be following to achieve this functionality? Or does this look like a no, no and I should be refactoring?
Thanks for looking
You can solve the circular reference problem using reflection, as Jon pointed out, but I suggest rethinking the design and refactoring it. Two suggestions.
Use interfaces to decuple A and B. (prefered solution)
Move the part needed by A and B into C and reference only C from A and B.
You need to specify the fully-qualified assembly name (including version etc, if it's strongly named) if you want Type.GetType to find a type which isn't in either mscorlib or the calling assembly.
For example:
// Prints nothing
Console.WriteLine(Type.GetType("System.Linq.Enumerable"));
// Prints the type name (i.e. it finds it)
Console.WriteLine(Type.GetType("System.Linq.Enumerable, System.Core, "
+ "Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"));
Alternatively, can you make this a generic method in the utility project, and get the caller to specify the type as a type argument?
You could look into dependency injection/ioc containers.
For example create an interface in the utility library and implement that in a specific class in the windows service. Then pass an instance to the utility class. This way the utility library doesn't have know anything about the windows service.
Sounds like a circular reference problem! You may need to refactor!