Reflection: how to call methods that take a class object as input

I am using reflection to call a method from another dll. This method takes a class object as input. How can I call this method. I tried to copy the same class to both dll libraries, and I created an object of this class and passed it. It throws an invliad conversion error at the very time of complie. Then I tried to let the function take the object as an argument, and then tried to apply it to the required class. This throws an invalid casting exception at run time. this is what i tried

            Test objTest = new Test("name","type");             
            Assembly assembly = Assembly.Load("MyProject.Components");             
            Type dllType = assembly.GetType("MynameSpace.MyClass");
            if (dllType != null)
            {
                MethodInfo m = dllType.GetMethod("MyFunction");
                object objdll;
                objdll = Activator.CreateInstance(dllType);
                object[] args = { objTest };
                if ((m != null))
                {                        
                    strReturnValue += (string)m.Invoke(objdll, args);                        
                }
            }

In the second dll, the method is similar to

public string MyFunction(Test obj)

My problem is that the class test is in a different assembly (the classes are in two different assemblies)

+3
3

. ( A), , . ( B), MyClass Test.

, Test, MyClass.MyFunction.

, Test A; . , , , . CLR, , .

, , , ( C), , A B. , Test , Test ​​ , . , A, B Test, , , .

-. A B, MyClass MyFunction ( ), , , ? MyFunction , A? MyClass , , , A, A MyFunction, :

        Assembly assembly = Assembly.Load("MyProject.Components");
        Type dllType = assembly.GetType("MynameSpace.MyClass");
        if (dllType != null)
        {
            IMyInterface instance = Activator.CreateInstance(dllType) as IMyInterface;
            if (instance != null) // check if this object actually implements the IMyInterface interface
            {
                instance.MyFunction(objTest);
            }
        }

, , . , , , A B, Test B, A - Test . factory, , - factory, Test. :

. - . "MyProject.Common". :

// define a simple factory interface
public interface IFactory
{
    object CreateInstance();
}

// and a generic one (hey, why not?)
public interface IFactory<T> : IFactory
{
    new T CreateInstance();
}

// define a Factory attribute that will be used to identify the concrete implementation of a factory
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public class FactoryAttribute : Attribute
{
    public Type FactoryType { get; set; }

    public FactoryAttribute(Type factoryType)
    {
        this.FactoryType = factoryType;
    }
}

IFactory factory , MyProject.Common.

, "MyProject.Components":

public class Test
{
    public string Name { get; set; }

    public string Type { get; set; }

    public Test(string name, string type)
    {
        this.Name = name;
        this.Type = type;
    }
}

public class TestFactory : IFactory<Test>
{
    #region IFactory<Test> Members

    public Test CreateInstance()
    {
        return new Test("name", "type");
    }

    #endregion

    #region IFactory Members

    object IFactory.CreateInstance()
    {
        return this.CreateInstance();
    }

    #endregion
}


public class MyClass
{
    // the Factory attribute on the first parameter indicates that the class TestFactory
    // should be used as a factory object to construct the argument for this method
    public string MyFunction([Factory(typeof(TestFactory))]Test obj)
    {
        if (obj == null)
            return null;
        else
            return obj.ToString();
    }
}

, , , :

        Assembly assembly = Assembly.Load("MyProject.Components");
        Type dllType = assembly.GetType("MynameSpace.MyClass");
        if (dllType != null)
        {
            MethodInfo m = dllType.GetMethod("MyFunction");
            object objdll;
            objdll = Activator.CreateInstance(dllType);

            // use the parameter information to construct the arguments
            ParameterInfo[] parameters = m.GetParameters();
            object[] args;
            if (parameters != null && parameters.Length > 0)
            {
                args = new object[parameters.Length];
                for (int i = 0; i < parameters.Length; i++)
                {
                    // check for factory attributes on the actual parameter
                    FactoryAttribute[] attributes = parameters[i].GetCustomAttributes(typeof(FactoryAttribute), true) as FactoryAttribute[];

                    // if no attributes were found, check the parameter type for factory attributes
                    if (attributes == null || attributes.Length == 0)
                        attributes = parameters[i].ParameterType.GetCustomAttributes(typeof(FactoryAttribute), true) as FactoryAttribute[];

                    // if no attributes were found still, then give up
                    if (attributes == null || attributes.Length == 0)
                    {
                        // this parameter has no factory specified,
                        // so how would this code know how to create the argument for that parameter ???
                        args[i] = null;
                        continue; // move on to the next parameter
                    }

                    // there should only be one factory attribute, so use the first one
                    // assumption made here is that all factory classes will have a parameterless constructor
                    IFactory factory = Activator.CreateInstance(attributes[0].FactoryType) as IFactory;

                    args[i] = factory.CreateInstance();
                }
            }
            else
                // there are no parameters
                args = null;


            if ((m != null))
            {
                strReturnValue += (string)m.Invoke(objdll, args);
            }
        }
+1

Type, ... .

object[] args = {typeof(typeneeded)};

object[] args = { assembly.GetType(typeneeded) };
0

MethodInfo.Invoke() :

public Object Invoke(
    Object obj,
    Object[] parameters
)

, - .

LINQPad, :

void Main()
{
    string strReturnValue = "";
    Test objTest = new Test("name","type");             
    Type dllType = typeof(MyClass);
    if (dllType != null)
    {
        MethodInfo m = dllType.GetMethod("MyFunction");
        object objdll;
        objdll = Activator.CreateInstance(dllType);
        object[] args = { objTest };
        if ((m != null))
        {                        
            strReturnValue += (string)m.Invoke(objdll, args);                        
        }
    }
}

public class Test
{
    public Test(string s1, string s2)
    {
    }
}

public class MyClass
{
    public string MyFunction(Test t)
    {
        return "";
    }
}

, MyClass, Test , ConstructorInfo:

Assembly assembly = Assembly.Load(); //assembly of "Test"
Type testType = assembly.GetType("Test");
ConstructorInfo ci = testType.GetConstructor(
                              BindingFlags.Public | BindingFlags.Instance, 
                              null, 
                              new Type[]{typeof(string), typeof(string)}, 
                              null);
Test objTest = ci.Invoke(new object[] { "name", "type" });

objTest .

0

Source: https://habr.com/ru/post/1763594/


All Articles