I'm trying to implement scripting capability to my application. I'm using the code below. Whenever I instantiate a new Api object, the application is supposed to quit (a little testing thing :p)
However, the application crashes at script.AddObject(...) with the error Specified cast is not valid. Is there a step I'm missing here?
public class ApiExposed
{
public string ModuleName;
public void Exit()
{
System.Environment.Exit(0);
}
}
public class Api
{
ScriptControlClass script;
ApiExposed ApiObj;
public Api()
{
ApiObj = new ApiExposed();
script = new ScriptControlClass();
script.Language = "VBScript";
script.AddObject("tbapi", (object)ApiObj, true);
script.Eval("tbapi.Exit()");
}
}
My guess is, the ApiExposed class is not COM visible - it will need to be in order for VBScript to interact with it.
I had similar problems to this.
Make sure you use [ComVisible(true)] on the class and methods.
Also, make your class PUBLIC!
Related
For a C# Project, I want to include a build step or something integrated in project that should raise build error if any developer is trying to use a specific method from framework classes, instead I want developers to use extension method for same. However I want to impose this as the compile time error. As an example, for a name sake I want developer on given project not to use string.Intern, instead should always use string.SpecialIntern. What are different ways to achieve this? I tried to use Roslyn-code-analysis but could not really write working rule for this, so I am not sure if tha'ts the right solution to this problem. Can someone guide me in details how to solve this with some examples?
This sounds like something you could accomplish with a custom code analyzer. I haven't tried it yet, but I believe it is possible to write your own analyzers.
This article from Microsoft claims to tell you how to do it:
https://learn.microsoft.com/en-us/visualstudio/extensibility/getting-started-with-roslyn-analyzers?view=vs-2017
Here's a direct link to the tutorial referenced in that article:
https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix
AFAIK there's no way to achieve what you're trying to do.
However, a solution would be to simply call the extension method.
public static class Extension
{
public static bool DoStuff(this Class stuff)
{
return false;
}
}
public class Class
{
public bool DontCallMe()
{
return this.DoStuff();
}
}
Class myClass = new Class();
myClass.DontCallMe();
Obviously, that only works if you can change the code of your class (which I suppose you aren't able to)
If that method is marked as virutal, you could create a Wrapper-Class which overrides that method.
public static class Extension
{
public static bool DoStuff(this Class stuff)
{
return false;
}
}
public class Class : Base
{
public override bool DontCallMe()
{
return this.DoStuff();
}
}
public class Base
{
public virtual bool DontCallMe()
{
return false;
}
}
Another approach would be to do what I described in this this post.
I understand this is only possible with a workaround. But why?
I want to add plugin support to my app. So I designed an abstract class that all future plugins will need to implement. Every plugin must implement a GetVersion() method like in this example code:
public abstract class Plugin
{
public abstract int GetVersion();
}
public class MyPlugin : Plugin
{
public override int GetVersion()
{
return 1;
}
}
This of course works perfectly as long as I instantiate the plugin before calling the GetVersion() method.
But if I want to get the version number of the plugin before creating an instance of it? To check compatibility for example?
public class Program
{
public Program()
{
if (MyPlugin.GetVersion() > 1)
{
PluginLoader.Load(new MyPlugin());
}
}
}
Although it might not answer directly your question "WHY" I think below solution might be usefull in your scenario:
Use assembly version attribute:
Assembly thisAssem = typeof(MyPlugin).Assembly;
AssemblyName thisAssemName = thisAssem.GetName();
Version ver = thisAssemName.Version;
It never can be done by C# because a static method cannot be implemented in derived classes.
Like the workaround, you can create a static factory to create the instance.
public abstract class Plugin
{
public abstract int GetVersion();
}
public class FactoryPlugin<T> where T : Plugin, new()
{
public static int GetVersion()
{
return new T().GetVersion();
}
}
public class Program
{
public Program()
{
if (FactoryPlugin<MyPlugin>.GetVersion() > 1)
{
}
}
}
Consider using the Factory pattern in a way similar to what a COM class factory does. You create two classes, your useful class, and a class factory class. Your class factory class implements IPluginFactory. You package it with your Plugin. The plugin factory has vary simple methods, but one of them allows your Plugin to be created. It's close to what #ThierryV showed, but without static methods. So the process is:
Use whatever you are planning to use to store and instantiate your plugins, but instead of instantiating a plugin, you instantiate the appropriate Plugin Factory
You can have the Plugin factory do what ever you want -- get detailed information about the plugin, allow instantiation of the latest version or a particular version of the plugin - go to town
But, eventually, you use an instance of the factory to instantiate your Plugin.
This is a good place to start: What exactly is a Class Factory?, but Don Box's Essential COM book is where I learned all this stuff, a long time ago in a place far away.
I am looking for this Java code's equivalent in C#
public class MainClass {
public MainClass() {
OtherClass o = new OtherClass(this); //I am looking for "this" keyword to send the instance
}
public void someMethod() {
}
}
public class OtherClass {
public OtherClass(MainClass m) { //and this receiver method
m.someMethod();
}
}
I think there should be a way in C# to sent the current class as a parameter so that I can call the someMethod() in MainClass from OtherClass ?
How can I do that in C#?
Thanks for help..
I am looking for this Java code's equivalent in C#
Well, no equivalency needed. Your code is already a valid C# code without any modification. Here is a demo.
Note: I would be very worried about the circular reference in your code, but I'm sure it was just a simple sample and you wouldn't actually implement code like that.
Important Note: Just to be clear, you are not sending the "class". That's just not possible. You are sending an instance of the class. Maybe that's what you meant, but just so nobody reads it and get confused.
I just tried to use Unity DI for, well, basic DI. Here is my setup:
C# Component project
public interface ILanguageBindings { ... }
C++/CX Component project
private ref class LanguageBindings : ILanguageBindings { ... }
public ref class LanguageImplementation {
public:
ILanguageBindings GetLanguageBindings();
}
C# Portable
public class Bootstrap {
private UnityContainer container;
public void Initialize(ILanguageBindings language) {
this.container.RegisterInstance<ILanguageBindings>(language);
}
}
C# App
var languageImpl = new LanguageImplementation();
var languageBindings = languageImpl.GetLanguageBindings();
var bootstrap = new Bootstrap();
bootstrap.Initialize(languageBindings);
I get the following error message from UnityContainer:
An exception of type 'System.ArgumentException' occurred in
Microsoft.Practices.Unity.DLL but was not handled in user code
Additional information: The type System.__ComObject cannot be
assigned to variables of type SparkiyEngine.Bindings.Language.ILanguageBindings.
I'm using 3.5.1405-prerelease version (the one that works on both Windows and Windows Phone). Is there a way to make this to work with Unity container since I'm using it in the rest of the project. If not, what are alternatives that support ComObjects?
Full code is on GitHub, I just pushed the problematic code.
Solved by changing
private ref class LanguageBindings : ILanguageBindings { ... }
to
public ref class LanguageBindings sealed : ILanguageBindings { ... }
Hi everyone smarter than me :-) I have another application which requires generation of an abstract class, and due to testing purposes is quite difficult to debug. therefor i created a wrapper and can define my abstract classes in visual Studio now (instead of native application)
However, the native application is expecting public abstract [obj type] values with only a get; method, and if i put in a set;, the application will bomb. Is there any way to set a field using Reflection or Mock to this field, and NOT have the set method?
//simplified class
public abstract class GetEUserAndDetails : [app specific interfaces]
{
public abstract Metastorm.Runtime.Types.Text paramFullNameLike
{
get;
set; //note: If i have this here, it will fail in Metastorm
}
public System.Data.DataSet Read()
{
//do something
}
}
and in Main() it's a c# winform, i have
Mock<Metastorm.Runtime.Models.MySampleProject.GetEUserAndDetails> mockMyBO = new Mock<Metastorm.Runtime.Models.MySampleProject.GetEUserAndDetails>() { CallBase = true };
//using reflection
foreach (PropertyInfo pi in mockMyBO.Object.GetType().GetProperties())
{
//simplified again, another form getting parameters and such
pi.SetValue(mockMyBO.Object, form.myTextParam, null);
}
If I don't have the set method, the pi.SetValue() line will fail, but if i do, it will fail in the native app. (note: i'm using the same test harness to test all sorts of abstract classes that will all implement the Read() method and need to test that it is pulling the correct data back, but the parameters will be different for each class.
Sorry if my code is bad i couldn't get it to format properly, and also please bear with me if i used the wrong terms. I'm not an expert by any means, just enough to be dangerous. I am just living with leaving the set; line for the moment and manually removing it before copy/pasting into the main application, but would like to find another way to do this for when there are many params.
If I understood your scenario correctly, you actually want to test the code in the abstract class, and not mock it.
With that in mind, I think the easiest approach in this case is simply to create a subclass within your test, that will inherit from your base class, and implement whatever is necessary for you to be able to test the base class.
Such as:
public class GetUserAndDetailsImplementation : GetEUserAndDetails
{
private Metastorm.Runtime.Types.Text _paramFullNameLike;
public override Metastorm.Runtime.Types.Text paramFullNameLike
{
get { return _paramFullNameLike; }
}
public void SetParamFullNameLike(Metastorm.Runtime.Types.Text text)
{
_paramFullNameLike = text;
}
}
And you can use that class as entry point for your testing.
Now if you really want to use a mock, have you tried the following?
var mock = new Mock<GetEUserAndDetails> { CallBase = true };
mock.SetupGet(x => x.paramFullNameLike).Returns(<some value>);