0

I have a C# application. It has a referenced class library Generic.dll. I have a Document class inside Generic.dll.

namespace Generic
{
    public class Document
    {
        public virtual string ObjectName()
        {
            return "Generic";
        }
    }
}

Then I created another class library Custom.dll and created a Document by inheriting the Document class in Generic.dll

namespace Custom
{
    public class Document : Generic.Document
    {
        public override string ObjectName()
        {
            return "Custom";
        }
    }
}

In my application I'm creating a Document object.

Document document = new Document();
Console.WriteLine(document.ObjectName());
Console.ReadLine();

When my application running if there is any way to tell the runtime if Custom.dll is available make Document object from Custom.dll or use Generic.dll?

NOTE: Custom.dll is not referenced to the application

EDIT:

I used the following method to create the object based on the Custom.dll availability. This will return Generic.Document object if either Custom.dll is not found nor couldn't load or will return Custom.Document if Custom.dll available.

public static T CreateObject<T>()
        {
            string zTypeName = typeof(T).Name;

            try
            {
                Assembly zLibrary = Assembly.LoadFrom(@"C:\Somewhere\Custom.dll");
                Type zType = zLibrary.GetType(string.Format("Custom.{0}", zTypeName), false, true);
                object zInstance = Activator.CreateInstance(zType);

                return (T)zInstance;
            }
            catch (Exception ex) 
            {
                Console.WriteLine(ex.Message);
                return (T)Activator.CreateInstance(typeof(T));
            }
        }

I used the above method to like this;

//Custom class
           Document custDocument = Utility.CreateObject<Document>();
           Console.WriteLine(custDocument.ObjectName());
           Console.ReadLine();

this will return the desired Document object. But can't we instruct the Runtime to get assembly when creating object uisng new keyword?

Irshad
  • 3,071
  • 5
  • 30
  • 51
  • 2
    I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders May 27 '15 at 05:32
  • This is where a IoC toolset like `Unity` would come in normally. You tell it `_container.Resolve()` but in your configuration somewhere you have `_container.RegisterType()` so it would return the custom version when you tried to resolve the generic version. – Scott Chamberlain May 27 '15 at 06:03
  • @ScottChamberlain can you explain it with an example? – Irshad May 27 '15 at 06:05
  • I just did in my previous comment. Go to [their web page](https://unity.codeplex.com/) and read a tutorial on it. (btw, if you did not know "IoC" stands for "Inversion of Control", this sometimes is interchangeable with "DI" or "Dependency Injection"). EDIT: Here is a direct link to the [DI tutorial](https://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx) – Scott Chamberlain May 27 '15 at 06:08
  • Could you use MEF instead? https://msdn.microsoft.com/en-us/library/dd460648%28v=vs.110%29.aspx – thomas May 27 '15 at 07:19

2 Answers2

1

Thanks to @MarcGravell found a solution to this problem. Refer these links to the original post.

Link 01

Link 02

The code as below;

    public class GenericProxyAttribute : ProxyAttribute
    {
        public override MarshalByRefObject CreateInstance(Type serverType)
        {
            string zTypeName = serverType.Name;

            try
            {
                Assembly zLibrary = Assembly.LoadFrom(@"C:\Assemblies\Custom.dll");
                Type zType = zLibrary.GetType(string.Format("Custom.{0}", zTypeName), false, true);
                return base.CreateInstance(zType);
            }
            catch (Exception)
            {
                return base.CreateInstance(serverType);
            }
        }
    }

    [GenericProxy]
    public class Document : ContextBoundObject
    {
        public virtual string GetObjectName() 
        {
            return "Generic Document"; 
        }
    }

Now when I initialize Document object;

Document document = new Document();

This actually calls the CreateInstance method of the GenericProxyAttribute class. There I load the Custom.dll and initiate a Document object. Then return the Custom.Document object. When the Custom.dll is not available returns the Generic.Document.

Community
  • 1
  • 1
Irshad
  • 3,071
  • 5
  • 30
  • 51
0

It is quite common to be able to select a custom implementation for an interface. As others have mentioned, there are Dependency Injection frameworks and there is lots of information about this subject.

This does require though that the application is configured to select one implementation or the other - you want your application to act differently if a custom implementation is available.

Instead of having to know the filename of the library, you could choose to provide the AssemblyQualifiedName of the type:

Type type = Type.GetType("Namespace.Type, AssemblyName", false);
if (type == null)
{
    type = typeof(T);
}

object instance = Activator.CreateInstance(type);

(Note that you can be more specific by supplying Version= and Culture=, and signed assemblies must include the PublicKeyToken= to be specified)

There is no built-in way to find all implementations of an interface - besides having to load and inspect all eligible assemblies and the security threat, it is generally not desired to have an application that behave differently based on the presence of a file.

C.Evenhuis
  • 25,996
  • 2
  • 58
  • 72
  • I happen to have written a DI config serializer and editor, which does inspect the directory for cancidates in order to create the config file - hoping to have the best of both worlds. If you're bored, you could check it out: http://blueprints.codeplex.com – C.Evenhuis May 27 '15 at 11:58