How do I dynamically call a class and use it's functions? - c#

I have a problem trying to dynamically call my class. This is my example code:
Class:
namespace TestUseCase
{
public class UseCase11
{
public UseCase11()
{
}
public string init()
{
return "aa.aspx";
}
}
}
Method to call the class:
private void dynamicExecution(string ClassName, string FunctionName)
{
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetEntryAssembly();
Object[] para = new Object[1];
para[0] = null;
object dynMyClass = assembly.CreateInstance(ClassName);
dynMyClass.GetType().GetMethod(FunctionName).Invoke(dynMyClass, para);
}
Usage:
dynamicExecution("TestUseCase.UseCase11", "init");
Unfortunately the result is always null. How can I resolve this issue?

Make sure that the class you are attempting to instantiate is declared in the right assembly. In your example you are using Assembly.GetEntryAssembly() but is that the correct assembly? If the class is defined in the same assembly as the code that you have shown you could also use Assembly.GetExecutingAssembly().

Related

Having similar method name with same parameter inside a class just with Interface name change

Just came across a code where a method with the same name is implemented within the class twice.
Once with the name only
Second with the Interface name and then the method name.
What is the concept called? I am unable to find the right direction. And if someone can explain it that would be great.
// Online C# Editor for free
// Write, Edit and Run your C# code using C# Online Compiler
using System;
public class HelloWorld
{
public static void Main(string[] args)
{
var obj = new AuthClass();
Console.WriteLine(obj.Login());
var obj2 = new AuthClass() as IAuth;
Console.WriteLine(obj2.Login());
//------------
}
}
public class AuthClass : IAuth
{
public string Login()
{
return "Method : You can be a developer";
}
string IAuth.Login()
{
return "Interface: Please learn the concepts";
}
}
public interface IAuth
{
string Login();
}

Exposing C# Code to VBA GetAutomationMethod Error

I am a relatively new coder and have never worked with C# or VBA before. I am currently trying to expose my C# code to VBA. I have been following the MSDN guide on how to do that.
I am running into an error when it comes to overriding my method:
public class AsynchronousClient : IAsynchronousClient {
protected override object GetAutomationObject(){
return this;
}
}
The error is:
'AsynchronousClient.GetAutomationObject()': no suitable method found to override.
I have been able to extract the interface and added the COMVisibleAttributes to my interface.
Any help or additional guidance on how to amend the code would be appreciated.
As mentioned by others, the steps you're following are specific to the VSTO technology, not for creating a DLL to use with VBA. Quite honestly, if you've never coded in either language before, this is probably not the best thing to start with...
Start with a Class project. You need GUIDs. You need an Interface, which your class needs to implement. And you need to specify how the class should work with the Interface. It needs to be set to the Type "None" for the Intellisense, etc. to work. The DLL needs to be COM-registered, as well.
Here's some test code I use, to give you an idea how the code part looks
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using vbForm = Microsoft.Vbe.Interop.Forms;
using office = Microsoft.Office.Core;
//[assembly: Guid("B5C4D7F5-C9B2-491e-91BA-63C208959190")]
namespace COM_ClassLib_CS
{
[Guid("BF78EB64-F59B-4086-9FC5-B87AA2002F4F")]
[ComVisible(true)]
public interface IVBAExtensions
{
string getTest(object app);
void formData(object formControl);
void passWordDoc(object doc);
object[,] returnArray();
string returnString();
}
[Guid("EC0B623E-E8A0-4564-84FB-2D8D149C8BA7")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class VBAExtensions : IVBAExtensions
{
public VBAExtensions()
{
}
//test using late-binding
public string getTest(object app)
{
object xlApp = app.GetType().InvokeMember("Application", System.Reflection.BindingFlags.GetProperty, null,
app, null);
object nm = xlApp.GetType().InvokeMember("Name", System.Reflection.BindingFlags.GetProperty, null,
xlApp, null);
string appName = nm.ToString();
object isReady = xlApp.GetType().InvokeMember("Ready", System.Reflection.BindingFlags.GetProperty, null,
xlApp, null);
string sReady = isReady.ToString();
return sReady;
}
//test calling from a UserForm, passing control as argument
public void formData(object formControl)
{
//string data = "";
vbForm.TextBox t = formControl as vbForm.TextBox;
t.Text = "test";
//return data;
}
//test passing doc object and accessing its Window
public void passWordDoc(object doc)
{
Microsoft.Office.Interop.Word.Document WordDoc = doc as Microsoft.Office.Interop.Word.Document;
WordDoc.ActiveWindow.Caption = "Tested!";
}
//test returning an array to VBA calling procedure
public object[,] returnArray()
{
//object[] array = new object[2] {"a", "b"};
object[,] array = new object[2, 2];
array[0, 0] = "a";
array[0, 1] = "1";
array[1, 0] = "b";
array[1, 1] = "2";
return array;
}
//test returning a string to VBA calling procedure
public string returnString()
{
return "AbC";
}
}
}
For more information you can reference https://msdn.microsoft.com/en-us/library/c3fd4a20.aspx and https://msdn.microsoft.com/en-us/library/ms973802.aspx
Your AsynchronousClient class is implementing the IAsynchronousClient interface, which I presume looks like this:
public interface IAsynchronousClient
{
object GetAutomationObject();
}
You would implement it like this:
public class AsynchronousClient : IAsynchronousClient
{
public object GetAutomationObject()
{
return this;
}
}
The error message says exactly what the problem is: there's nothing to override there. You use the override method when you're implementing abstract or virtual methods, not interface members.
Remove the override keyword and you'll be good. Below snippets show situations where override would be applicable:
public abstract class AsynchronousClientBase
{
public abstract object GetAutomationObject();
public virtual object GetFoo()
{
return null;
}
}
public class AsynchronousClient : AsynchronousClientBase
{
public override object GetAutomationObject()
{
return this;
}
public override object GetFoo()
{
return new Foo();
}
}
The MSDN article you linked to says to "Override the GetAutomationObject method of a host item class in your project" - this implies your type should be derived from a base class that defines a virtual or abstract GetAutomationObject method.

Why SatisfyImportsOnce method doesn't work with the object parameter?

I have been following this MSDN example about the CompositionContainer class (System.ComponentModel.CompositionHosting):
[Export]
class MyAddin
{
public String myData { get { return "The data!"; } }
}
class MyProgram
{
[Import]
public MyAddin myAddin { get; set; }
}
class Program
{
static void Main(string[] args)
{
AggregateCatalog catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(typeof(MyAddin).Assembly));
CompositionContainer _container = new CompositionContainer(catalog);
MyProgram myProgram = new MyProgram();
_container.SatisfyImportsOnce(myProgram);
Console.WriteLine(myProgram.myAddin.myData);
Console.ReadLine();
_container.Dispose();
}
}
But when I try to compile it, this error message is generated:
Error 2 The best overloaded method match for
'System.ComponentModel.Composition.Hosting.CompositionContainer.SatisfyImportsOnce(System.ComponentModel.Composition.Primitives.ComposablePart)'
has some invalid
arguments X:\Dev\S-L\CSharp\EtceteraSolution\CompositionContainer_Demo\CompositionContainer_Main.cs 15 13 CompositionContainer_Demo
Sample source: http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.hosting.compositioncontainer%28v=vs.110%29.aspx
You are missing extension method that can do it. You just need to add correct using on top of your program. I guess the example doesn't show the necessary usings.
The method you're looking for is: public static ComposablePart SatisfyImportsOnce(this ICompositionService compositionService, object attributedPart);
Add using System.ComponentModel.Composition on your program, and the extension method should work fine.
Alternatively, it's also possible to call extensionmethod like this:
AttributedModelServices.SatisfyImportsOnce(_container, myProgram);
Note, it's in .NET framework >= 4.0.

How can I handle recursive composition in MEF?

Consider the following code sample that uses MEF to create an object of type Importer that imports an object of type ImporterExporter which in turn imports an object of type Exporter, i.e. Importer -> ImporterExporter -> Exporter. The catalog is managed by a CompositionUtility (obviously simplified for this example).
I know that MEF will resolve imports recursively on imported parts. However, because I want to have the option to instantiate each of these classes independetly, every class with imports also composes itself in its constructor to resolve those imports.
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
namespace MefRecursionSample
{
class Program
{
static void Main(string[] args)
{
// var importerExporter = new ImporterExporter(); // include this and composition will work
var importer = new Importer();
Console.Write(importer.ImporterExporter.Exporter.Value); // should print 7
Console.ReadKey();
}
}
class CompositionUtility
{
static CompositionUtility()
{
var executingAssembly = Assembly.GetExecutingAssembly();
var assemblyCatalog = new AssemblyCatalog(executingAssembly);
_compositionContainer = new CompositionContainer(assemblyCatalog);
}
private static CompositionContainer _compositionContainer;
private static bool _isComposing;
public static void Compose(object part)
{
_compositionContainer.ComposeParts(part);
}
}
class Importer
{
public Importer()
{
CompositionUtility.Compose(this);
}
[Import]
public ImporterExporter ImporterExporter { get; set; }
}
[Export]
class ImporterExporter
{
public ImporterExporter()
{
CompositionUtility.Compose(this);
}
[Import]
public Exporter Exporter { get; set; }
}
[Export]
class Exporter
{
public int Value { get { return 7; } }
}
}
Running the code as is leads to a composition error "The ComposablePart of type MefRecursionSample.Importer' cannot be recomposed....", obviously because I am trying to explictly compose something that MEF also wants to compose.
What surprised me, was the fact that when I included the first line of the Main method, i.e. create an object of type ImporterExporter without MEF, this "double-composition" no longer caused an exception. Why is that?
Also, how could I make it work such that I could instantiate each of these indepennetly, yet also make them compose themselves when chained as in the sample. I figured I would introduce a boolean flag _compositionInProgress on the CompositionUtility and immediately return from Compose() when the flag is set to avoid the recursive composition. Is there a better way?
The flag I considered setting in the CompositionUtility's Compose method does not work, because there can be cases where the string of automatic imports is interrupted. For instance, in the question's example if Exporter instantiated a class in its constructor using new and this class would want to compose itself. Under the original solution, that class' call to Ccompose would return immediately, leaving the class uncomposed.
Because I want classes to compose themselves (thus making it unneccessary for their users to even know about MEF), the only solution was to establish the rule that classes with an [Export] attribute must not call Compose(this). Because they will be composed automatically by MEF when being imported, this would result in "double composition" and thus throw an exception.
If it is a requirement that classes marked with [Export] have to instantiated independently via new instead of nly imported via MEF, they have to have an addional constructor with a boolean flag which when set well trigger composition of that class. The default behavior, however, has to be no composition in order to avoid the aforementioned "double composition".
why not simply do this?
class Program
{
private static CompositionContainer _compositionContainer;
static void Main(string[] args)
{
//compose the container just one time in your app
var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
_compositionContainer = new CompositionContainer(assemblyCatalog);
var importer = _compositionContainer.GetExportedValue<Importer>();
Console.Write(importer.ImporterExporter.Exporter.Value); // should print 7
Console.ReadKey();
}
}
[Export]
class Importer
{
[ImportingConstructor]
public Importer(ImporterExporter imex)
{
this.ImporterExporter = imex;
}
public ImporterExporter ImporterExporter { get; private set; }
}
[Export]
class ImporterExporter
{
[ImportingConstructor]
public ImporterExporter(Exporter exporter)
{
this.Exporter = exporter;
}
public Exporter Exporter { get; private set; }
}
[Export]
class Exporter
{
public int Value { get { return 7; } }
}
What you really want to do (I think) is calling container.SatisfyImportsOnce() on an object and not ComposeParts .
ComposeParts adds all exports tree to the catalog while SatisfyImportsOnce each object is to itself , composing parts and thats it , no registeration of recursive exports , so you can call constructor or use importing constructor , you can have both.
James.

Question on calling a method using reflection

Beautiful sunny day today! However, I can't enjoy it because I've been trying to call a dynamic method in Mono for 2 days :-(
The Story:
I'm trying to call it within a class called 'Template'. Basically I would love it if I could pass a string to Template and have it run that method, which is defined within the Template class. The template class looks like this so far..
namespace Mash
{
public class Template
{
public Template(string methodToCall)
{
Type type = this.GetType();
object ob = Activator.CreateInstance(type);
object[] arguments = new object[52];
type.InvokeMember(methodToCall,
BindingFlags.InvokeMethod,
null,
ob,
arguments);
}
public void methodIWantToCall()
{
Console.WriteLine("I'm running the Method!");
}
}
}
No errors are received during compile time. Once I run it, however, I get
'Unhandled Exception: System.MissingMethodException: Method not found: 'Default constructor not found...ctor() of Mash.Template'.'
I think it is failing here:
object ob = Activator.CreateInstance(type);
If you need any more information please let me know.
Thanks in advance!!
you don't need another instance of Template if the method you want to call is in the same class.You can use this
public class Template
{
public Template(string methodToCall)
{
this.GetType().InvokeMember(methodToCall,
BindingFlags.InvokeMethod,
null,
this,
null);
}
public void methodIWantToCall()
{
Console.WriteLine("I'm running the Method!");
}
}
I tested it with:
class Program
{
public static void Main(string[] args)
{
Template m = new Template("methodIWantToCall");
Console.ReadKey(true);
}
}
The first argument of Activator.CreateInstance is the type of the class, and then follows the argument of the constructor of the type.
You're trying to create an instance of the Template class using no parameter for the constructor. But there isn't a constructor with no parameter.
Try adding a constructor into your Template class, which takes no parameters:
public class Template
{
//......
public Template()
{
}
}

Categories