C#, accessing classes from a referenced project - c#

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!

Related

VS tells me to add a reference to an seemingly unrelated assembly. How to find out why?

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

How can I pass a reference type between Assemblies referencing a common DLL?

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?

Can you access an object through two layers of assemblies?

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.

C# - Circular Reference and cannot see Namespace

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.

Use an interface from an external assembly that's marked as "internal" (C#)

I'd like to implement an interface that resides in an external assembly. However that particular interface has been marked as "internal". Is there a way I can still implement this interface for my own classes?
I know how to call private/internal methods using reflection in C#, so I guess reflection should be used in this case too. However, I don't know how. And yes, I do know it usually isn't wise to use internal/private stuff, but in this case I see no other solution.
Update: I'm not able to edit / change the external assembly in any way. It should be left untouched.
You can't do that, unless you can change the assembly containing the interface to add an InternalsVisibleToAttribute, targeting your own assembly.
Use the InternalsVisibleToAttribute in the external assembly to point to the assembly that you want to expose internal types to.
http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx
Just to get some background, presumably you want to pass the interface implementation to something else in this assembly, which is also internal, because otherwise they wouldn't have been able to compile this other assembly (it being an error to refer to an internal type in a public method's parameters).
I think you'll have to use Reflection.Emit to build a type that implements the interface, having obtained the interface's Type object by reflection. Not exactly a straightforward task, and the result will be fragile because you're digging around in the internals of someone else's assembly.
Other options:
Disassemble the other assembly, using
Reflector and that cool addin that
builds a whole project from the
assembly.
Talk to the owner of the other assembly and explain your needs to
them
I you have the source of the external assembly then you can compile it with an InternalsVisibleTo attribute pointing at your assembly. This is not a perfect solution and I often use it for unit testing rather than production code but it may be something worth looking at.
Basically all you would need to do is add the following to the AssemblyInfo.cs code-file in your project:
[assembly: InternalsVisibleTo("YourAssembly")]
If YourAssembly is strongly-named then you have to put the fully qualified name of the assembly including the entire public key (not just the token).

Categories