Click here to Skip to main content
15,889,876 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
How to Invoke and retrieve data from a method inside a dll using interface?
INFO:
we are using windows forms and sql server2005,we pass data as xml and uses stored procedures .In the application layer client is not providing internet,mean while the business and database layer have internet connectivity.
we have placed business object class files as dll in a shared folder of client machine which has internet connectivity.how can i call a function inside the dll ,pass parameters through an interface class inside the dll and retrieve the output
on the Business layer we have an interface class "IGetData"
C#
namespace WNHRP01BO
{
   public interface IGetData
    { 
        string GetData(string Xml, string ClassName, string Mode);
    }
}

class file in the Business layer having function "GetData" ,which is to be called is shown below
C#
namespace WNHRP01BO
{
    public class hb007001C0 : WNHRP01BO.IGetData
	{
		PLABS.DbProvider _objDb = PLABS.DbProvider.MSSql;
		public hb007001C0()
		{
			
		}
		#region IGetData Members
		public string GetData(string Xml,  string AddParams,string Mode)
		{
			String retXml = string.Empty;
			if (Mode == "I")
				{
					PLABS.DAL objDbHelper = new PLABS.DAL();
					retXml= objDbHelper.insertSP("hb007001F0_IU", Xml, this._objDb);
				}
            return retXml;
     
		}
		#endregion
	}
}


"CallBOCommon" a class in application layer ,through which the business layer is connected either using webservice or referenced project as shown below
C#
namespace UtilsApp
{
    public class CallBOCommon
    {
        public String CallWS(String Xml, String ClassName, String Mode)
        {
          //////calling from referenced business object project "WNHRP01BO"
          //// Type tp = Type.GetType(ClassName);
//String retDat = (((WNHRP01BO.IGetData)Activator.CreateInstance(tp)).GetData(Xml, "", Mode));
     ////   return retDat;

       //////////calling webservice
         //Connector.AuthWS obj = new Connector.AuthWS();
         //Xml = PLABS.Utils.Compress(Xml);
 //String retDat = obj.CallWS(Xml, ClassName, Mode, "http://somehostingserver.in/service.asmx");
          //return retDat;

///actually what i am trying to impliment is to replace below lines 
//String retDat = (((WNHRP01BO.IGetData)Activator.CreateInstance(tp)).GetData(Xml, "", Mode));
//return retDat;with ur provided code 
//but i dont know how to specify the type of Activator.CreateInstance(tp) 
//as (WNHRP01BO.IGetData) while loading from dll

  //////i am getting class name as "WNHRP01BO.hb007001C0,WNHRP01BO"
 //////BOClass =WNHRP01BO.hb007001C0
 string BOClass = ClassName.Split(',')[0].ToString();
/////////reading from dll on the shared folder of client machine
 Assembly a = Assembly.LoadFile(@"D:\DLL\live hrp\WNHRP01BO.dll");
 var aTypes = a.GetTypes();
 Type t = aTypes.FirstOrDefault(tp => tp.FullName == BOClass);
// how to specify the type of Activator.CreateInstance(tp) as (WNHRP01BO.IGetData)
 object obj = Activator.CreateInstance(t);
/////cant list GetRuntimeMethods() from type
     MethodInfo MI = t.GetMethods().FirstOrDefault(m1 => m1.Name.IndexOf("GetData") > 0);
 var retVal = MI.Invoke(obj, new object[] { Xml, ClassName, Mode });
////am getting value Of MI as Null
//////what am i missing here?

        }

    }
Posted
Updated 10-Mar-14 0:54am
v2

I think you can do something like the following:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace Test_Reflection2
{
    class Program
    {
        static void Main(string[] args)
        {
            // load assembly
            Assembly l = Assembly.LoadFile(@"d:\tmp\Test_ReflectionSampleLib.dll");
            // types in that assembly
            var ts = l.GetTypes();

            // find interface
            Type i = ts.FirstOrDefault(t1 => t1.Name == "IGetData" && t1.IsInterface);
            // find class which implements interface
            Type c = ts.FirstOrDefault(t1 => t1.IsClass && t1.GetInterface("IGetData") != null);
            // create an instance of class
            object o = Activator.CreateInstance(c);
            // get method. not good way to find the method!!
            MethodInfo mi = c.GetRuntimeMethods().FirstOrDefault(m1 => m1.Name.IndexOf("IGetData.GetData") > 0);
            // invoke it
            var retval = mi.Invoke(o, new object[] { string.Empty, string.Empty, string.Empty });
            Console.WriteLine(retval);
        }
    }
}
 
Share this answer
 
Comments
george4986 7-Mar-14 19:52pm    
thanks for the reply ;-)
i will try ur solution and get back to u soon .
george4986 10-Mar-14 7:51am    
I have tried below code also , shows error

string BOClass = ClassName.Split(',')[0].ToString();

Assembly a = Assembly.LoadFile(@"D:\DLL\live hrp\WNHRP01BO.dll");

var aTypes = a.GetTypes();

Type t = aTypes.FirstOrDefault(tp => tp.FullName == BOClass);

Type iT = aTypes.FirstOrDefault(tp => tp.Name=="IGetData");

object obj = (iT)Activator.CreateInstance(t);

MethodInfo MI = t.GetMethods().FirstOrDefault(m1 => m1.Name.IndexOf("GetData") > 0);

var retVal = MI.Invoke(obj, new object[] { Xml, ClassName, Mode });
george4986 10-Mar-14 6:16am    
whats the use of Type i in ur code?is it needed?
george4986 10-Mar-14 6:20am    
actually what i am trying to impliment is to replace below lines

String retDat = (((WNHRP01BO.IGetData)Activator.CreateInstance(tp)).GetData(Xml, "", Mode));

return retDat;with ur provided code

but i dont know how to specify the type of Activator.CreateInstance(tp)

as (WNHRP01BO.IGetData) while loading from dllmy code

//////i am getting class name as "WNHRP01BO.hb007001C0,WNHRP01BO"

//////BOClass =WNHRP01BO.hb007001C0

string BOClass = ClassName.Split(',')[0].ToString();

Assembly a = Assembly.LoadFile(@"D:\DLL\live hrp\WNHRP01BO.dll");

var aTypes = a.GetTypes();

Type t = aTypes.FirstOrDefault(tp => tp.FullName == BOClass);
// how to specify the type of Activator.CreateInstance(tp) as (WNHRP01BO.IGetData)

object obj = Activator.CreateInstance(t);

/////cant list GetRuntimeMethods() from type

MethodInfo MI = t.GetMethods().FirstOrDefault(m1 => m1.Name.IndexOf("GetData") > 0);

var retVal = MI.Invoke(obj, new object[] { Xml, ClassName, Mode });

////am getting value Of MI as Null
smithjdst 10-Mar-14 15:12pm    
You could try switching from MethodInfo to ConstructorInfo. Also, is the method your invoking public, are the input values in same order and same types as the method parameters?
In your Application Layer right click on the project and select add reference then choose location of "WNHRP01BO.dll" and ok.
Now in CallBOCommon class import the namespace WNHRP01BO and access the class "hb007001C0".
Create object for this class and call getdata() through this object.

Thanks,
-RG
 
Share this answer
 
Comments
george4986 7-Mar-14 19:52pm    
thanks for the reply ;-)
i will try ur solution and get back to u soon .
george4986 10-Mar-14 6:31am    
that won't work what u suggested is in commented lines of my quetion

//////calling from referenced business object project "WNHRP01BO"
//// Type tp = Type.GetType(ClassName);
//// String retDat = (((WNHRP01BO.IGetData)Activator.CreateInstance(tp)).GetData(Xml, "", Mode));
//// return retDat;

but the dll location is on client side ,i need to load dll not as reference
Try this, I have tested and it works.
using dynamic to try an prevent need for Assembly references & Type casting.

public object CallWS(string Xml, string ClassName, string Mode) {
    try {

    Assembly a;
    if ((a = Assembly.LoadFile(@"D:\DLL\live hrp\WNHRP01BO.dll")) != null) {
        var aTypes = a.ExportedTypes.ToArray();

        Type t;
        string BOClass = ClassName.Split(',')[0].ToString();
        if ((t = aTypes.FirstOrDefault(tp => tp.FullName == BOClass)) != null) {
            object obj = Activator.CreateInstance(t);
            object igd = (dynamic)obj.GetType().GetInterface("IGetData");
            object value;

        //option 1:------------------------------------>>
            value = ((dynamic)igd).InvokeMember(
                            "GetData", 
                            BindingFlags.InvokeMethod | 
                            BindingFlags.Instance | 
                            BindingFlags.Public,
                            null,
                            obj,
                            new object[] { Xml, ClassName, Mode }
                    );

        //option 2:------------------------------------>>
            MethodInfo mi = ((dynamic)igd).GetMethod("GetData");
            value =  mi.Invoke(obj, new object[] { Xml, ClassName, Mode });

            return value;
        }
    }

    return null;
    } 
    catch { return null; }
}
 
Share this answer
 
v4
Comments
george4986 13-Mar-14 0:16am    
am using .NET3.5 and i think the keyword dynamic is .net4.0 compatable
and
code line "var aTypes = a.ExportedTypes.ToArray();"
works like below here
"var aTypes = a.GetExportedTypes().ToArray();"
george4986 13-Mar-14 0:24am    
my working code now on local machine is this

if (ClassName.StartsWith("WNHRP01BO")) {

Assembly a = Assembly.LoadFile(@"\\KS50\Query\Source Exchange\hrptest remote\WNHRP01BO.dll");

var aTypes = a.GetTypes();

Type t = aTypes.FirstOrDefault(tp => tp.FullName == BOClass && tp.GetInterface("IGetData") != null);

Type iT = aTypes.FirstOrDefault(tp => tp.Name == "IGetData" && tp.IsInterface);

object obj = Activator.CreateInstance(t);

MethodInfo MI = t.GetMethods().FirstOrDefault(m1 => m1.Name == "GetData");

var retVal = MI.Invoke(obj, new object[] { Xml, ClassName, Mode });

return retVal.ToString(); }

above code is working it lists methods in dll now am facing a problem with connection string here we use another dll for db connectivity .if businessobject is referenced from application it connects using an xml file in debug folder similarly on 3 tier it reads from the hosted path bin using another dll .the dll doesn't read from remote machine other than above setups.both dll's are part of a framework we are using and there source is not available.

thanks for ur reply.am working on it now,if u have any suggestions plz reply

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900