I know the title sounds a bit strange, but this has been boggling my mind for a little bit. So Intel offers this TurboBoost sidebar gadget with calls using JavaScript, and I want to write a program from scratch in C# that does the same thing. The calls stem from what I believe is an ActiveX DLL which I easily imported. The problem is, whenever I try to call a function, it gives me the error "an object reference is required for the non-static field..." I've found all of the functions e.g. the one I used return a dynamic data structure. I've tried splitting up the functions and made them both static but still no luck. Here's the code(ITurboBoostClient is the interface portion):
namespace TurboBoostMon_CLI
{
class Program
{
public static object GetCPUFreq()
{
object n = ITurboBoostClient.GetCurBaseFrequency(); //<---- error
//return Convert.ToDouble(n);
return n;
}
public static void Main(string[] args)
{
object cpubasefreq = GetCPUFreq();
Console.WriteLine(cpubasefreq); // neglect the output for now
}
}
}
If typical naming conventions are being used, ITurboBoostClient is an interface, and you do not have an instance of an object that implements the interface. Hence, the error.
Without knowing more about the ActiveX DLL, its hard to say exactly what to do, but it would be along the lines of:
{
ITurboBoostClient myClient = TurboBoostFactory.GetInstance();
object n = myClient.GetCurBaseFrequencey();
return n;
}
Note that in the first line, you call a static method that can product the class (with the interface) that is required. Then you can actually use that interface.
Look again through the ActiveX library you imported, and see if you can find a factory method, a CreateInstance method, or some other instantiator that will create the initial object.
If you're getting that error, then you need to declare something as a new object. Assuming your error marker is correct, you need to change that to create a new instance of some object that inherits the ITurboBoostClient, then use that to call the GetCurBaseFrequenct() method.
Something like:
ITurboBoostClient myTurboBoost = new TurboBoostClientObject(); // Making names up here, not familiar with the framework you're working with.
object n = myTurboBoost.GetCurBaseFrequency();
Sorry I don't know what class you need to instantiate there, but a short dig on google will most surely be revealing.
Related
I'm trying to wrap a COM API so that others can use my wrapper without knowing anything about the wrapped API. However, I've hit a problem trying to use some of the items from the COM API.
Let's say the COM API has a method that returns an object defined within the API.
IComChildObject IComObject.GetChildObject()
If I have a reference to the dll that defines the COM API, I can easily use this as follows...
IComChildObject childObject = myComObjectInstance.GetChildObject();
The problem I have, is that I need to be able to work with the IComChildObject through the wrapper class, without referencing the COM API dll.
I tried to create an interface in my wrapper, that would accomplish this. So inside my wrapper project, I have an interface like this.
public interface ILocalChildObject : IComChildObject{}
Then I added a property to my wrapper, that I thought would allow my external code to use the IComChildObject.
public class ComWrapper
{
IComObject comObject;
public ILocalChildObject ComChildObject { get { return comObject.GetChildObject() as ILocalChildObject;}}
}
When I run the following code from my external code, the ChildObject is null
ILocalChildObject ChildObject = myComWrapper.ComChildObject;
I'm obviously doing something wrong, but I'm in over my head on this and don't even know what to search Google for.
Maybe it's not clear what I'm trying to do, or maybe I'm trying to do something strange here. I want to create a wrapper class library in such a way, that the code that uses it doesn't have to know anything about the wrapped library. I've done okay so far, up until the point where I need to use objects from the wrapped library in the external code. I could easily resolve this by referencing the wrapped library in my external project, but I'd like to avoid doing that.
Basically, I just need a way to use the IComChildObject in my external code, without adding a reference to the COM API dll.
Any help would be greatly appreciated,
If your API is based on IDispatch you could use the dynamic keyword, something like this:
dynamic childObject = GetChildObjectSomehow();
childObject.CallAnyMethod() // compile will always succeed, will be resolved at runtime (and failed if there's like a typo error)
Note dynamic is not available on .NET core for COM objects yet.
If it's not (if it's based on IUnknown), then you'll have to declare this interface either in an external dll or .tlb, or directly in your C# code, so it can be called by the .NET runtime. You don't have to use the original .dll, you can redefine the interface by yourself if needed (maybe a simplfied version). But the runtime has to know the binary layout to be able to call it.
Another way to handle this, as Hans Passant points out, is to wrap the COM API object in a class. Then you can access the properties within the object through the new object. The only downside to this approach is there's a lot of typing, as you have to recreate any properties or methods that you want to access in the COM API object.
In the wrapper project, you'll create a class that will contain the object returned from the API. This class will also have properties and methods, that allow a user to manipulate the API object through the class.
public class LocalChildObject
{
internal IComChildObject ComChildObject;
public string ChildObjectProperty { get { reutrn ComChildObject.ChildObjectProperty; } set { ComChildObject.ChildObjectProperty = value ;}}
public LocalChildObject(IComChildObject ComChildObject)
{
this.ComChildObject = ComChildObject;
}
}
In this example, ComChildObject is the object returned from the API. Then there's a property in the class ChildObjectProperty, which allows you to get or set the ChildObjectProperty of the ComChildObject.
Then in my main wrapper class, I can have a property that returns this new object (which contains the API COM object).
public class Wrapper
{
public LocalChildObject GetLocalChildObject { get { return new LocalChildObject(ComObject.GetChildComObject());}}
}
Then in the external code I can make changes to the object through the new wrapper object
LocalChildObject localObject = myWrapperInstance.GetLocalChildObject;
localObject.ChildObjectProperty = "A new string";
This method requires recreating all the properties and methods that you want to expose through the wrapper, however, it does allow the user using the wrapper to use IntelliSense.
Is there a way I can initialize a class which contains a static constructor (that throws an exception), without executing the static constructor?
I've tried these so far:
Activator.CreateInstance(typeof(Foo));
FormatterServices.GetUninitializedObject(typeof(Foo));
var s = new XmlSerializer(typeof(Foo));
Foo f = (Foo)s.Deserialize(new StringReader("<Foo></Foo>"));
Aside from using a CRL Profiler api with something like MS Fakes or TypeMock, can this be done using any API in the baseclass library, or perhaps something unmanaged.
Example class that I want to use.
public class Foo
{
static Foo()
{
throw new Exception("Populate Bar from the database, which isn't available.");
}
public int Bar { get; set; }
}
No, not that I'm aware of, at least directly.
Static constructors are there exactly to be automatically called whenever anything happens either to anything (method, property, ...) static from the class, or when you create the very first instance of that class (if it's possible).
This means, basically, that they are kind of always called, whether you like/want it or not. It's always automatic and it always happens.
One option, though, would be to use some nasty reflection to extract working code, replace (or entirely remove) static constructor and rebuild the class from scratch.
This might help a bit on this.
Problem is that another great question arises: how to replace that type during its usage. If it comes from an interface, it might be easier, but if it's a concrete type being directly called, you have got yourself a great challenge.
Now, if you take this to a higher abstraction level, this issue might be solved using other approaches, like proxying that request to some other database, or even translating it to another language.
I'm trying to make an expansion setup for this game I'm developing, (not going to go into detail about), but all a single expansion will need is the 1 .dll file added into the Expansions folder I have added.
I have figured out how to access these .dll added into this folder as seen below:
Assembly ExpAssembly = Assembly.LoadFrom("Expansions/Intrique.dll");
Type myType = ExpAssembly.GetTypes()[0];
Here is an example of the class I'm trying to load:
public class Expansion: MyGame.Expansion {
public Expansion() {
//Stuff
}
public string SomeMethod()
{
return "Test";
}
}
Calling the following code runs SomeMethod() just fine
MethodInfo Method = myType.GetMethod("SomeMethod");
object myInstance = Activator.CreateInstance(myType);
MessageBox.Show(Method.Invoke(myInstance, null).ToString());
But what I want to do is be able to write Expansion expObj; and assign it by calling new Expansion() from this not-referenced .dll, but not in the library itself.
(For the purposes of this answer, I'm going to assume that your Expansion subclass is has a fully qualified name of Intrique.Expansion. I.e. the namespace is the same as the name of the DLL).
Because your main program does not reference Intrique.dll, the code in your main program cannot use the types in that DLL directly. That is, Intrique.Expansion is not a usable type in the context of the written code of your main program, though it can be used at run-time.
Taking your code example literally, the only approach likely to work given the code you have now would be to use dynamic:
dynamic myInstance = Activator.CreateInstance(myType);
myInstance.SomeMethod();
This is because SomeMethod() is declared only in Intrique.Expansion. There's not any other type you could use statically in your main program where that method is known.
If that method was instead an implementation of a member of some interface that Intrique.Expansion implements and which your main program references, or was an override of some virtual member of MyGame.Expansion (which presumably your main program references, if not actually declares), then you could cast the instance to the interface type or MyGame.Expansion respectively and call the method that way:
ISomeInterface myInstance = (ISomeInterface)Activator.CreateInstance(myType);
myInstance.SomeMethod();
or:
MyGame.Expansion myInstance = (MyGame.Expansion)Activator.CreateInstance(myType);
myInstance.SomeMethod();
Finally, given that you are trying to implement some kind of extensibility architecture, you might consider using the Managed Extensibility Framework, which is designed specifically to handle a lot of the messy parts of exactly this kind of thing.
I just ran into the strangest thing and I'm a bit mind = blown at the moment...
The following program compiles fine but when you run it you get a RuntimeBinderException when you try to read Value. 'object' does not contain a definition for 'Value'
class Program
{
interface IContainer
{
int Value { get; }
}
class Factory
{
class Empty : IContainer
{
public int Value
{
get { return 0; }
}
}
static IContainer nullObj = new Empty();
public IContainer GetContainer()
{
return nullObj;
}
}
static void Main(string[] args)
{
dynamic factory = new Factory();
dynamic container = factory.GetContainer();
var num0 = container.Value; // WTF!? RuntimeBinderException, really?
}
}
Here's the mind blowing part. Move the nested type Factory+Empty outside of the Factory class, like so:
class Empty : IContainer
{
public int Value
{
get { return 0; }
}
}
class Factory...
And the program runs just fine, anyone care to explain why that is?
EDIT
In my adventure of coding I of course did something I should have thought about first. That's why you see me rambling a bit about the difference between class private and internal. This was because I had set the InternalsVisibleToAttribute which made my test project (which was consuming the bits in this instance) behave the way they did, which was all by design, although alluding me from the start.
Read Eric Lippert's answer for a good explanation of the rest.
What caught me really of guard was that the dynamic binder takes the visibility of the type of the instance in mind. I have a lot of JavaScript experience and as a JavaScript programmer where there really isn't such a thing as public or private, I was completely fooled by the fact that the visibility mattered, I mean after all, I was accessing this member as if it was of the public interface type (I thought dynamic was simply syntactic sugar for reflection) but the dynamic binder cannot make such an assumption unless you give it a hint, using a simple cast.
The fundamental principle of "dynamic" in C# is: at runtime do the type analysis of the expression as though the runtime type had been the compile time type. So let's see what would happen if we actually did that:
dynamic num0 = ((Program.Factory.Empty)container).Value;
That program would fail because Empty is not accessible. dynamic will not allow you to do an analysis that would have been illegal in the first place.
However, the runtime analyzer realizes this and decides to cheat a little. It asks itself "is there a base class of Empty that is accessible?" and the answer is obviously yes. So it decides to fall back to the base class and analyzes:
dynamic num0 = ((System.Object)container).Value;
Which fails because that program would give you an "object doesn't have a member called Value" error. Which is the error you are getting.
The dynamic analysis never says "oh, you must have meant"
dynamic num0 = ((Program.IContainer)container).Value;
because of course if that's what you had meant, that's what you would have written in the first place. Again, the purpose of dynamic is to answer the question what would have happened had the compiler known the runtime type, and casting to an interface doesn't give you the runtime type.
When you move Empty outside then the dynamic runtime analyzer pretends that you wrote:
dynamic num0 = ((Empty)container).Value;
And now Empty is accessible and the cast is legal, so you get the expected result.
UPDATE:
can compile that code into an assembly, reference this assembly and it will work if the Empty type is outside of the class which would make it internal by default
I am unable to reproduce the described behaviour. Let's try a little example:
public class Factory
{
public static Thing Create()
{
return new InternalThing();
}
}
public abstract class Thing {}
internal class InternalThing : Thing
{
public int Value {get; set;}
}
> csc /t:library bar.cs
class P
{
static void Main ()
{
System.Console.WriteLine(((dynamic)(Factory.Create())).Value);
}
}
> csc foo.cs /r:bar.dll
> foo
Unhandled Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
'Thing' does not contain a definition for 'Value'
And you see how this works: the runtime binder has detected that InternalThing is internal to the foreign assembly, and therefore is inaccessible in foo.exe. So it falls back to the public base type, Thing, which is accessible but does not have the necessary property.
I'm unable to reproduce the behaviour you describe, and if you can reproduce it then you've found a bug. If you have a small repro of the bug I am happy to pass it along to my former colleagues.
I guess, at runtime, container method calls are just resolved in the private Empty class, which makes your code fail. As far as I know, dynamic can not be used to access private members (or public members of private class)
This should (of course) work :
var num0 = ((IContainer)container).Value;
Here, it is class Empty which is private : so you can not manipulate Empty instances outside of the declaring class (factory). That's why your code fails.
If Empty were internal, you would be able to manipulate its instances accross the whole assembly, (well, not really because Factory is private) making all dynamic calls allowed, and your code work.
I'm trying to make a list of all the runtime constructed classes created by a generic class. In other words, if I have a class:
public GenericCls<T> {
public void Reset() { ... }
...
}
And I have code in various places like this:
GenericCls<int> gci = new GenericCls<int>();
GenericCls<String> gcs = new GenericCls<String>();
GenericCls<float> gcf = new GenericCls<float>();
...
Can I get something like this?:
Type[] allconstructed = GetAllConstructed(typeof(GenericCls<>));
which returns {GenericCls<int>,GenericCls<String>,GenericCls<float>,...}
The use case involves a generic allocator, that supports any type of object allocation (it's like new XXX(), but nicer to the garbage collector). I won't go into specifics, because it will just complicate the question. Basically, I will not know all the constructed classes at compile time, since the library is a dll intended to be used with a separate code project. So I will need some form of reflection that I can't seem to find on the interwebs.
Assembly.GetExecutingAssembly().GetExportedTypes() does not contain anything but the base generic class (i.e. typeof(GenericCls<>))
typeof(GenericCls<>).GetGenericArguments() returns only Type "T", which is not only an invalid type, but entirely useless.
Is it even possible to find all constructed classes of a generic class if you only know the generic class' type? (typeof(GenericCls<>);) I'm not sure if "constructed" is the right word - I want to know either all the concrete generic-derived classes currently active, or all of these that will ever exist (not sure how C# handles generic construction behind the scenes).
#David MÃ¥rtensson: Your answer gave me an idea. I could make a static list of types in any non-generic class, and register each constructed class as it was constructed (when T is known).
i.e.
static public class ConcreteList {
static public List<Type> concrete;
}
public class GenericCls<T> {
static GenericCls() {
ConcreteList.concrete.Add(typeof(GenericCls<T>));
}
}
I checked it with ConcreteList.concrete[x].GetGenericArguments(), and it's working. Oh snap.
You might use a factory class to create instances, that way the factory class could keep a list of all created classes.