How to get an object from a loaded dll - c#

I see this question a fair amount on SO, and I've followed that advice, but I appear to be doing something wrong. The dll seems to load in fine but the object CreateInstance is returning is null.
I have this dll:
namespace Backfill
{
public class Module : Kernel.Module
{
public override void ModuleStart()
{
//Stuff
}
}
}
In another DLL with a DIFFERENT namespace
namespace Kernel
{
public abstract class Module
{
public abstract void ModuleStart();
}
public static void KernelStart()
{
string load_dll = #"Path to DLL";
Assembly test_dll = Assembly.LoadFile(load_dll + ".dll");
Module test_mod = (Module)test_dll.CreateInstance("Kernel.Module");
test_mod.ModuleStart();
}
}
(Module)test_dll.CreateInstance("Kernel.Module"); is returning null, though. Any idea why?

(Module)test_dll.CreateInstance("Kernel.Module")
This won't work. As you specified, the Module class which you're trying to instantiate (which, I assume, is the one from the first DLL), is not in the Kernel namespace, but in the Backfill namespace. You should therefore have something along these lines:
(Module)test_dll.CreateInstance("Backfill.Module")

Kernel.Module is an abstract class. You cannot create an instance of it directly. You need to create an instance of the derived class.
Edit: Since supplying more info:
#Antonijn has the same answer. You need to specify the type that you want directly. BackFill.Module seems like the correct one.
Before Edit:
If you have the same names in multiple assemblies then yo need to use a fully qualified (including assembly name) for the type you want. For exmaple: https://stackoverflow.com/a/2300428/30225 as an possible answer.

Related

C# internal Access Specifiers,

I have Created one ConsoleApplication to understand Access Specifiers.
Below is my code for internal, I can access this class from outside the Assembly.
namespace Assembly_1 //This is first assembly.
{
public class Base
{
//internal class
internal class B
{
public static void fnB()
{
Console.WriteLine("fnB");
}
}
}
}
namespace Assembly_2 //This is second assembly.
{
public class Derived : Assembly_1.Base
{
public class D
{
public void fnD()
{
B.fnB();//how can I access this class?
}
}
}
}
And this is where I am Accessing it.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Assembly_2.Derived.D d = new Assembly_2.Derived.D();
d.fnD();
}
}
}
My Question
Right now I can Access Class B and it's methods like fnB() in Derived.
Everything works fine. but How?
How can I access the B Class outside Assembly_1?
As I worte in the comments:
You are confusing the namespace and assembly terms.
You can read about it here:(Assemblies and Namespace)
Many namespaces can be defined in a single assembly.
If you would like to check and understand the internal modifier,
then you would have to create a new class library project (that will compile into a different assembly), define the Base class there
and add a reference to it in your main console application.
Then you will see that you don't have access to it anymore and the code will not compile.
How can I access the B Class outside Assembly_1?
Because you're confusing namespaces and assemblies. An assembly is a collection of one or more namespaces, contained within a .dll or .exe file.
See also: MSDN: Assemblies in the Common Language Runtime and Understanding and Using Assemblies and Namespaces in .NET.
What you call Assembly_1 and Assembly_2 are namespaces within the same assembly.
Because internal members are visible within the same assembly, you can use Assembly_1.B from Assembly_2.D, because both namespaces reside in the same assembly.

Private-ish method?

Within my projects I often want to have a method (or function if you prefer) that is private, however I also want to access it from ONE other class. Is this a possibility?
To clarify, this method can be accessed from ClassA, its own class but not any other.
There are plenty of ways to do this untill your last statement that is "and ONLY that class", i can only think of 1 way to do that and it is to have the classes laid out in assemblies as such as such:
Assembly A only contains class A with the method you want declared as internal
Assembly B declared as a friendly assembly : https://msdn.microsoft.com/en-us/library/0tke9fxk.aspx and contains code to call A (it can as to it it is internal as if in the same assembly as it is a friend assembly)
No other assembly linked to A , B or both will be able to call the method on class A as it is internal.
The best way that I can think of is this.
In C# 5, a set of caller information attributes were added, namely [System.Runtime.CompilerServices.CallerMemberName], [System.Runtime.CompilerServices.CallerFilePath], and [System.Runtime.CompilerServices.CallerLineNumber]. We can use the CallerFilePathAttribute to see whether the caller comes from a particular .cs file.
Usually, one file will only contain one class or struct. For example, ClassA is defined in ClassA.cs. You can check if the caller file name matches ClassA.cs in the method.
So modify your method's parameters like this:
([CallerFilePath] string callerFilePath = "" /*Other parameters*/)
In the method, check if the callerFilePath matches the file path of ClassA. If it does not, throw an exception saying that the method can only be accessed from ClassA!
You can make this method protected, if it suits your OOP structure:
public class A
{
protected void Test()
{
Console.WriteLine("I can only be called from B");
}
}
public class B : A
{
public void Pub()
{
Test();
}
}
And there many other ways to do this.
However, in general, it sounds like a wrong look at access modifiers.
If you want to only call your method from exactly one place, then just call it from exactly one place.
The fact that this method should be called from another class, makes him public, logically and architecturally.
Another simple way to control member access is using delegates.
Let's assume you have a private method:
class SecureMethod {
private void DoSomething() { }
}
You can provide access to this method by injecting delegate to this method:
class ClassA {
public ClassA(Action secureMethod) { }
}
SecureMethod objWithSecureMethod;
var a = new ClassA( objWithSecureMethod.DoSomething );
I'm showing you how do to this, but these are very bad practices:
public class A
{
private void CanOnlyCallMethodInClassB();
public static void SetHandlerCanOnlyCallMethodInClassB(ClassB b)
{
b.MethodFromClassA = CanOnlyCallMethodInClassB;
}
}
public class B
{
public Action MethodFromClassA { get; set; }
}
in code:
var b = new B();
A.SetHandlerCanOnlyCallMethodInClassB(b);
b.MethodFromClassA();
but better way is to use object of ClassB in method's classA. Search google for strategy pattern or use inheritance.
Whatever you are asking is not possible in C#. I mean you can not allow only one class to use private method. All you can do is to use internal which allows classes of just one assembly to access your methods or protected which is accessible within its class and by derived class instances!
Apart from that There is not any thumb rule for what you are asking but you can do some hack as shown below:
MethodInfo privateMethod = instance.GetType().GetMethod("NameOfPrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);
privateMethod.Invoke(instance, new object[] { methodParameters });
One slightly dirty trick to use a method from class B in class A is to make the method protected rather than private and derive A from B.
Another possibility, probably better, is to make the method internal rather than private and then put class A and B in the same assembly.

Activator.CreateInstance: Dynamic Instantiation of Classes

I am designing a loosely-coupled structure. I want to call classes from different assemblies/namespaces via a code which is represented by a String. My design is, each of client's business rules is on different assemblies and not dependent on each other (ONE client is to ONE DLL ratio) so that when I made an update on business rules of 1 client, it would not affect the others. My attention now is on using Factory Design and using Activator.CreateInstance() Method.
This is the project setup (2+n DLL's)
namespace Foundation; // where the interfaces/abstract resides
namespace Factory; // has dependency on Foundation assembly
namespace Client1; // client1's DLL, no dependency
namespace Client2; // client2's DLL, no dependency
The UI // only referenced to the Foundation and Factory not the Clients
The actual code
namespace Foundation
{
public interface IBusinessRules
{
string GetBusinessRule();
}
}
namespace Client1 //DLL for client 1
{
public class BusinessRules : Foundation.IBusinessRules
{
public string GetBusinessRule()
{
return "Client1 Business Rule";
}
}
}
namespace Client2 //DLL for client 2
{
public class BusinessRules : Foundation.IBusinessRules
{
public string GetBusinessRule()
{
return "Client2 Business Rule";
}
}
}
namespace Factory
{
public static class Invoker<T> where T: Foundation.IBusinessRules
{
public static T FetchInstance(string clientCode)
{
return (T)Activator.CreateInstance(Type.GetType(clientCode));
}
}
}
//sample implementation that generates unhandled Exception
using Factory;
using Foundation;
static void Main(string[] args)
{
//the parameter is maintained in the database
IBusinessRules objClient1 = Invoker<IBusinessRules>.FetchInstance("Client1");
//should call Client1.BusinessRules method
Console.WriteLine(objClient.GetBusinessRule());
Console.Read();
objClient = Invoker<IBusinessRules>.FetchInstance("Client2");
//should call Client2.BusinessRules method
Console.WriteLine(objClient.GetBusinessRule());
Console.Read();
}
Any idea why my sample doesn't work? And any suggestion to improve the design?
Thanks in advance.
How about using
Expression.Lambda
anyone?
If you use FetchInstance("Client.BusinessRules") your code works, IF everything is in the same assembly. If it's not (as per your design) you need to give an AssemblyQualifiedName.
I would do the design differently though. Keep your call with just "Client1" as Parameter but change the implementation of the Factory. Dynamically load the assembly for the given client (with Assembly.Load() or Assembly.LoadFrom()), then use clientAssembly.CreateInstance() to istantiate your type.
Edit: Crude code sample:
namespace Factory
{
public static class Invoker<T> where T: IBusinessRules
{
public static T FetchInstance(string clientCode)
{
var clientAssembly = Assembly.LoadFrom(clientCode + ".dll");
return (T)clientAssembly.CreateInstance(clientCode+".BusinessRules");
}
}
}
If you dont't know the class name in the client-dll, you have to search for an applicable Type, for example with clientAssembly.GetTypes().
Thanks to your help guys i finally Got it! I just modify the Factory
namespace Factory
{
public static class Invoker<T> where T : Foundation.IBusinessRules
{
public static T FetchInstance(string clientCode)
{
Type objType = Type.GetType(clientCode + ".BusinessRules," + clientCode);
return (T)Activator.CreateInstance(objType);
}
}
But I wonder about its effeciency (performance hit) because it uses Reflection..
You need to use the full name of the class.
for example:
Type.GetType("System.Collections.Generic.Dictionary`2[System.String,[MyType,MyAssembly]]")
If you are loading the type from an external assembly, I would recommend using Activator.CreateInstanceFrom.
var typeReference = Activator.CreateInstanceFrom(assemblyPath, fullyQualifiedClassName);
return typeReference.Unwrap() as T;
If you want to be able to add business rules as dlls after deployment and create them at runtime, I suggest you have a business rules folder under you app, load all dlls in that app, search for all types that implement of IBusinessRules in each dll using reflection. Given that you now have handles on the types, creating one based on name would be easy and your project would scale out.
Either that, or pass the assembly qualified name of the classes to your methods.

Namespace-only class visibility in C#/.NET?

In C#, can you make a class visible only within its own namespace without living in a different assembly? This seems useful for typical helper classes that shouldn't be used elsewhere.
(i.e. what Java calls package-private classes)
You can make the classes internal but this only prevents anyone outside of the assembly from using the class. But you still have to make a separate assembly for each namespace that you want to do this with. I'm assuming that is why you wouldn't want to do it.
Getting the C# Compiler to Enforce Namespace Visibility
There is an article here (Namespace visibility in C#) that shows a method of using partial classes as a form of "fake namespace" that you might find helpful.
The author points out that this doesn't work perfectly and he discusses the shortcomings. The main problem is that C# designers designed C# not to work this way. This deviates heavily from expected coding practices in C#/.NET, which is one of the .NET Frameworks greatest advantages.
It's a neat trickā€¦ now don't do it.
I don't think that what you want is possible.
internal is assembly (strictly speaking module) privacy. It has no effect on namespace visibility.
The only way to achieve privacy of a class from other classes within the same assembly is for a class to be an inner class.
At this point if the class is private it is invisible to anything not in that class or the outer class itself.
If protected it is visible to everyone that could see it when private but is also visible to sub classes of the outer class.
public class Outer
{
private class Hidden { public Hidden() {} }
protected class Shady { public Shady() {} }
public class Promiscuous { public Promiscuous() {} }
}
public class Sub : Outer
{
public Sub():base()
{
var h = new Hidden(); // illegal, will not compile
var s = new Shady(); // legal
var p = new Promiscuous(); // legal
}
}
public class Outsider
{
public Outsider()
{
var h = new Outer.Hidden(); // illegal, will not compile
var s = new Outer.Shady() // illegal, will not compile
var p = new Outer.Promiscuous(); // legal
}
}
In essence the only way to achieve what you desire is to use the outer class as a form of namespace and restrict within that class.
No, it is possible. You can use internal class in another assembly.
For example I have a internal string extension class that located in SharMillSoft.Core assembly, if I want use it in another assembly that name is SharpMilSoft.Extension, I must use assembly attribute like as below:
using System;
using System.Linq;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("SharpMilSoft.Extensions")]
namespace SharpMilSoft.Core.Extensions.Strings.Public
{
internal static class SharpStringExtensions
{
public static bool IsNullOrEmpty(this string data)
{
return string.IsNullOrEmpty(data);
}
}
}
And I use this class in SharpMilSoft.Extension assembly like as below:
namespace SharpMilSoft.Extensions.Strings
{
public static class SharpStringExtensions
{
public static bool IsNullOrEmpty(this string data)
{
return Core.Extensions.Strings.Public.SharpStringExtensions.IsNullOrEmpty(data);
}
}
}
Note: Then SharpMilSoft.Extensions assembly will be friend assembly for SharpMilSoft.Core assembly
For more details about friend assembly, you can visit this link : Friend assemblies
If you have a single assembly you can define as many namespaces in that assembly as you want but no matter what modifier you apply in the IDE you will always be able to see the classes in other namespaces.
Not sure if it is directly possible, but a few good ways to fake it would be:
1) Have the classes that need this sort of stuff inherit from a single class which has the helper class as an internal class.
2) Use extension methods and then only reference the extension methods within the namespace.

Can I declare a variable of Type<T> without specifying T at compile time?

How do I Load the class "MyContent" dynamically ?
I have 1 interface<T>, 1 abstract generic class<T> and 1 class. Check my code out:
public interface IMyObjectInterface{
}
public abstract MyAbstractObject : IMyObjectInterface{
}
public class MyObject : MyAbstractObject{
}
public interface IMyContentInterface<T> where T : MyAbstractObject
{
void MyMethod();
}
public abstract MyAbstractContent<T>, IMyContentInterface<T> where T : MyAbstractObject
{
public abstract void MyMethod();
}
public public class MyContent : MyAbstractContent<MyObject>
{
public override void MyMethod() { //do something }
}
I am trying but obviously it's not working:
IMyObjectInterface obj = (IMyObjectInterface)Assembly.Load("MyAssembly").CreateInstance("MyObject");
IMyContentInterface<obj> content = (IMyContentInterface<obj>)Assembly.Load("MyAssembly").CreateInstance("MyContent");
content.MyMethod();
//assembly and type names are correct
If I change IMyContentInterface<obj> to IMyContentInterface<MyObject>, works :
IMyContentInterface<MyObject> content = (IMyContentInterface<MyObject>)Assembly.Load("MyAssembly").CreateInstance("MyContent");
content.MyMethod();
//assembly and type names are correct
The problem is that i don't what is going to be my object in the 2nd line, when defining IMyContentInterface<T>. Please, does somebody know how to do it in .NET Framework 4.0?
the item in the < > has to be a type not an object.
my car is an object of the type car so
Car myCar=new Car();
i want a list to keep my cars (objects of type Car) in.
List<Car> myCars = new List<Car>();
And then we add object of type Car to my List.
myCars.Add(myCar);
myCars.Add(anotherCar);
How do I Load the class "MyContent" dynamically?
Loading it isn't hard - you already know how to do that, but C# generics are strongly-typed, checked and guaranteed at compile time. Consider this code:
List<string> list = new List<string>();
list.Add(new TcpSocket()); // This line won't compile
The C# compiler couldn't tell you this was illegal if you were allowed to declare generics like this:
Type type = GetTypeFromReflectedAssembly();
List<type> list = new List<type>();
// This *might* work - who knows?
list.Add(new TcpSocket());
If your ultimate goal is to call MyContent.MyMethod() and that doesn't have anything to do with the generic type parameter <T>, consider declaring a non-generic interface you can implement somewhere in your inheritance hierarchy and declare your instance variable using that:
IMyContentInterface content = (IMyContentInterface)Assembly.Load("MyAssembly").CreateInstance("MyContent");
content.MyMethod();
I had to read this a few times, but I figured out what you're asking. :) This question is a specific instance of this other question:
Pass An Instantiated System.Type as a Type Parameter for a Generic Class
That said, here's an example of how you might use it for your test case. Obviously you can vary it. Also, don't miss my final note at the end of this answer.
Assembly MyCompany.MyProduct.MyComponent:
Define your interfaces in this assembly:
namespace MyCompany.MyProduct.MyComponent
{
public interface IMyObjectInterface
{
void MyObjectMethod();
}
/* It's important to include this non-generic interface as a base for
* IMyContentInterface<T> because you will be able to reference this
* in the assembly where you load components dynamically.
*/
public interface IMyContentInterface
{
Type ObjectType
{
get;
}
void MyContentMethod();
}
public interface IMyContentInterface<T> : IMyContentInterface
where T : IMyObjectInterface
{
}
}
Assembly MyCompany.MyProduct.MyComponent.Implementation:
Implement the interfaces in this assembly that will be dynamically loaded.
namespace MyCompany.MyProduct.MyComponent
{
public abstract class MyAbstractObject : IMyObjectInterface
{
public abstract void MyObjectMethod();
}
public class MyObject : MyAbstractObject
{
public override void MyObjectMethod() { }
}
public abstract class MyAbstractContent<T> : IMyContentInterface<T>
where T : MyAbstractObject
{
public Type ObjectType
{
get
{
return typeof(T);
}
}
public abstract void MyContentMethod();
}
public class MyContent : MyAbstractContent<MyObject>
{
public override void MyContentMethod() { }
}
}
Assembly MyCompany.MyProduct
Your program is composed in this assembly, a term I pulled from the Managed Extensibility Framework. This assembly references MyCompany.MyProduct.MyComponent but not MyCompany.MyProduct.MyComponent.Implementation under the assumption that the interfaces are more likely to remain compatible than the implementations during product development. This design is an attempt to favor cohesion over coupling (a pair of often misunderstood words), but the actual implementations tend to vary heavily in their success of achieving this goal.
namespace MyCompany.MyProduct
{
using MyCompany.MyProduct.MyComponent;
using System.Reflection;
using System.Security.Policy;
public class ComponentHost
{
public void LoadComponents()
{
Assembly implementation = LoadImplementationAssembly();
/* The implementation assembly path might be loaded from an XML or
* similar configuration file
*/
Type objectType = implementation.GetType("MyCompany.MyProduct.MyComponent.MyObject");
Type contentType = implementation.GetType("MyCompany.MyProduct.MyComponent.MyContent");
/* THIS assembly only works with IMyContentInterface (not generic),
* but inside the implementation assembly, you can use the generic
* type since you can reference generic type parameter in the source.
*/
IMyContentInterface content = (IMyContentInterface)Activator.CreateInstance(contentType);
}
private Assembly LoadImplementationAssembly()
{
/* The implementation assembly path might be loaded from an XML or
* similar configuration file
*/
string assemblyPath = "MyCompany.MyProduct.MyComponent.Implementation.dll";
return Assembly.LoadFile(assemblyPath);
}
}
}
Final Note:
The Managed Extensibility Framework was built as a common solution to the problem you are working on. Having worked with it for a while now, I say with confidence that it has the following nice properties:
Relatively short learning curve.
Very clean code as a result.
Low runtime cost (the assembly is small and performance is quite good).
I would easily recommend it as serious viable option for someone working on a new application if it meets any combination of one or more of the following:
The application is divided into components (as almost any non-trivial application would be).
The application needs to be flexible or extensible in the future (as any long-term project would be).
The application needs to dynamically load an implementation from an unknown assembly.
This is a way to dynamically load a Interface. This assumes you have some way of getting the assembly you are trying to load it from and a string for the name of the type.
In my case I used an Xml file. You can use any, I don't show those methods, because it can change per your implementation.
ISomeInterface myInterface = this.GetComponent<ISomeInterface>("SomeImplementation");
public T GetComponent<T>(string componentName)
{
// A method to dymanicly load a .dll, not shown in this example
Assembly assembly = this.GetComponentAssembly(componentName);
// A method to get a string assembly type, in this case from another source
string assemblyType = this.GetAssemblyType(componentName);
T component = (T)assembly.CreateInstance(assemblyType);
return component;
}

Categories

Resources