I lately have had to change a piece of code to allow compatibility with an older version DLL. The DLLs have the same name and are not signed. The difference also is in some additional methods added to the new DLL.
One way to go about this which doesn't seem right to me is to reference the new DLL in the project, build and run. If you want to use the other DLL, you just replace it in the bin folder. You can avoid errors by just checking the existence of a method in a constructor somewhere using Reflection, and set a flag so that later on you can avoid calling the new functions if you are using the older version.
The strange thing to me is that the following piece of code doesn't work when using the old version:
int[] someVariable = (DLLIsNewFormat) ? DLL.CallNewMethod() : new int[5];
Basically what is happening is that the DLLIsNewFormat is False but for some reason I get the error:
Method not found: 'Int32[] [NameSpace].[Class].CallNewMethod()'.
I understand that the best way to go about this is to probably check if each function exists and then calling them using reflection. But I just don't know why the code is behaving this way. Is this just undefined behavior?
This is happening at the time that the method containing your snippet is JIT-compiled. In order for JIT-compilation to happen, the method needs to be available at the time the method is invoked. Since the method is not available, the JIT-compiler throws this exception when the method containing this code is called, before the method is even executed.
One way around this would be to define a new method:
int[] HideCall()
{
return DLL.CallNewMethod();
}
Then call this method instead of DLL.CallNewMethod() directly.
A better solution would be to define an interface in an assembly that is referenced by both your "conditional DLL" and the assembly you are conditionally using this DLL from. Have a default implementation of this interface available in the main assembly, and an alternate implementation in the conditionally-used DLL.
Then, at runtime, you can simply see if the DLL is available, use reflection to construct an instance of the class that implements this interface, and then substitute out a the reference to your default implementation with this one.
Example code:
// Interface, in an assembly visible to both of the other assemblies.
public interface IDLLInterface
{
int[] CallNewMethod();
}
// Implementation in the main program.
class DefaultDLLImplementation : IDLLInterface
{
public int[] CallNewMethod()
{
return new int[5];
}
}
static class DLLImplementation
{
public readonly IDLLInterface Instance;
static DLLImplementation()
{
// Pseudo-code
if (DllIsAvailable) {
Instance = ConstructInstanceFromDllUsingReflection();
} else {
Instance = new DefaultDLLImplementation();
}
}
}
Then you can use DLLImplementation.Instance.CallNewMethod() instead, and the right method will be called automatically.
Of course, I would suggest naming your interface with a more descriptive name so that it's apparent what it means.
What you want is to hide calls to non-existing methods from JIT.
To do so you need to make sure each of non-existent calls made in inside a function and call to such function is controlled by version condition:
private int[] WrappedNewMethod()
{
return DLL.CallNewMethod();
}
...SomeOtherMethod()
{
int[] someVariable = (DLLIsNewFormat) ? WrappedNewMethod(): new int[5];
}
Related
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 created the Class1.GetChild<T>() where T : DependencyObject extension method in lib1.dll assembly. After that, all assemblies that depends on lib1.dll failed to compile with error:
The type 'System.Windows.DependencyObject' is defined in an assemebly
that is not referenced. You must add a reference to assembly
'WindowsBase' etc...
Why dependent assemblies requires WindowsBase even if they don't use GetChild?
.
To reproduce (vs2010 .net4):
lib1.dll (references WindowsBase)
namespace lib1
{
public static class Class1
{
public static T GetChild<T>(this DependencyObject src) where T : DependencyObject
{
return default(T);
}
}
public static class Class2
{
public static int SomeExtMethod(this string src)
{
return 0;
}
}
}
lib2.dll (references lib1 but not WindowsBase)
using lib1;
class someClass
{
void someFct()
{
"foo".SomeExtMethod(); // error: The type 'System.Windows.DependencyObject'
// is defined in an assemebly that is not referenced.
// You must add a reference to assembly 'WindowsBase' etc..
}
}
.
Update:
I think there's definitly something when mixing generic methods and extension methods. I tried to demonstrate the issue in the following sample:
// lib0.dll
namespace lib0
{
public class Class0 { }
}
// lib1.dll
using lib0;
namespace lib1
{
public static class Class1
{
public static void methodA<T>() where T : Class0 { } // A
public static void methodB(Class0 e) { } // B
public static void methodC(this int src) { } // C
}
public static class Class2
{
public static void methodD(this String s) { }
}
}
// lib2.dll
using lib1;
class someClass
{
void someFct()
{
Class2.methodD(""); // always compile successfully
"".methodD(); // raise the 'must add reference to lib0' error depending on config. see details below.
}
}
A, //B, //C -> compile ok
A, B, //C -> compile ok
//A, B, C -> compile ok
A, //B, C -> raise error
A, B, C -> raise error
//A means methodA is commented. As Damien pointed out, type inference might play some role. Still curious to know the ins and outs.
Your situation has been answered by Microsoft here:
https://connect.microsoft.com/VisualStudio/feedback/details/668498/problem-with-extension-method-in-c-compiler
There are other use-cases as well independent of extension methods which produce this error wrongly.
Consider this:
Define a generic method in a type, say TP1, defined in library say LB1.
Type constrain the generic method on some type defined in some other library LB2.
Define another method in TP1.
Now in your library reference only LB1 and try to call the second method of type TP1
If you don't use TP1 but some other type defined in LB1, you do not get the error.
Also, even if one of the method of type TP1 expects a parameter of the type defined in LB2 (and you do not call this method) it does not produce this error
When one assembly depends on another assembly, the first assembly also depends on all the dependencies of the other--regardless of what is used. Assembly dependencies are effectively decoupled, another version of either assembly can be deployed after compilation, the compiler can't know that under circumstances like this one or more of the dependencies in the second assembly won't be used by the first assembly.
To solve the issue you can simply add a reference to WindowsBase.
Or, as prashanth points out, put the SomeExtMethod into a different assembly so code that uses that doesn't need to take a dependency on WindowsBase.
Update:
If you don't use anything from an assembly, you don't need any of its dependencies. But, as soon as you use one assembly, you need all the dependencies of that assembly as well. This is apparent in the way Visual Studio add references. If you add a reference to an assembly, it will copy all the dependent assemblies (not registered in the GAC) into your debug/release directories along with the assembly you added.
Update:
As to the compile error: that's the way it was written--there may be no other reason. Is it a good idea to get a compile error if you don't reference dependent assemblies? Maybe, you're likely to use something from a reference and that might use something directly from the references references--better a compile error than a deployment error.
Why not a compile error on every non-referenced secondary dependency? Again, it was written that way. Maybe an error here too would be good; but that would be a breaking change and would require really persuasive reasons.
I'm not sure this can be answered by anyone other than someone on the compiler team. I'm now thinking that it's to do with type inference - but whereas §7.6.5.1 Method Invocations talks about inference, §7.6.5.2 Extension method invocations is silent on the matter - despite the fact that inference obviously does take place when searching for applicable extension methods.
I think it's attempting some form of inference before it's performing the comparison on identifiers (which would immediately rule out the extension method since it's got the wrong name). Obviously, it can't perform any form of inference for this type if it's unable to understand the type constraints.
Hence, when you change your type constraint to just class, it now successfully passes over this method - it can infer a type parameter, but it now eliminates this extension method successfully.
When you reference another assembly, I assume the compiler needs to be able to parse any method signatures defined in that assembly, so it knows where to go to find that function if it sees a call to it.
If you replace your GetChild() function with
public static T GetChild<T>(this T src)
{
if (typeof(T) == typeof(DependencyObject)) return default(T);
else return default(T);
}
or something similar to that, it does not require you to include the reference to WindowsBase that you're running into. But if you add where T : DependencyObject to the signature, it does require it.
Effectively, you can use whatever assembly references you want in a project, so long as you don't expose them in any way. Once you expose them, then every other project which uses your library needs to be able to handle them, and thus requires those references themselves.
Maybe ILMerge would solve this problem. The idea is you create 2 dlls and merge them into one. That way you can have a single dll but reference it twice. Then way you can separate the GUI code from other code and only add the reference that you need to the particular project.
The answer is simple. It is because the method is decalre as public. This mean that it is visible to lib2.dll (in your case.) In other word you can call this method.
It also has a constrain that only classes inherited from DependencyObject can call this method. So that is the reason why you need to reference 'WindowsBase'.
I have a DLL written in C#. In this DLL there is a class that is defined.
Let's assume that the code of this DLL is :
namespace unloadableDLL
{
public class DivisionClass
{
public /*static*/ long Division(long x, long y)
{
// We deliberately do not use a try catch to catch divide by 0 exceptions
return (x / y);
}
}
}
Now, I want to load dynamically this DLL in a test program. I need to see what happens if I divide by zero in the two following cases :
1) DLL is loaded directly (without using an AppDomain)
2) DLL is not loaded directly, an AppDomain is created first and then it loads the DLL.
I'm completely new in C#, by new I mean I've started less than 4 hours ago but I have a C++ background.
My problem is that in my test program, I need to instanciate a DivisionClass Object but this one is declared only in the DLL.
=> Resolved
My test program is
class Program
{
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
static void Main(string[] args)
{
// Load the DLL
Console.WriteLine("Attempting to load unloadableDLL");
Assembly a = Assembly.LoadFrom("./unloadableDLL.dll");
unloadableDLL.DivisionClass divisionObject = (unloadableDLL.DivisionClass)a.CreateInstance("unloadableDLL.DivisionClass");
long number = divisionObject.Division(8, 2);
Console.WriteLine(number);
}
}
I don't know what but the compilers keeps telling me that Static member unloadableDLL.DivisionClass.Division(lon, long) cannot be accessed with an instance reference; qualify it with a typename instead.
Thank you all
To load into a separate AppDomain an execute the method from there - use reflection as in the following StackOverflow question. It does get involved as is typically a more advanced C# topic but the code is fairly boilerplate and for a man with C++ knowledge it shouldn't present problems.
For a direct call then follow the methods outlined above - i.e. reference the dll in your project and instantiate through code as per Oded (who has deleted his answer unfortunately so reproducing below)
DivisionClass.Division(1, 2)
EDIT
If the methods are not static
Invoking a method via reflection
Assembly myAssembly1 = Assembly.LoadFrom("myPath\\Assembly1.dll");
Type myType = myAssembly1.GetType("MyClass");
object myObject = Activator.CreateInstance(myType);
myType.Invoke("myMethodName", BindingFlags.InvokeMethod, null, myObject, null);
In a separate App Domain adds to the complexity - see link.
Also I don't think your Division class will work as is. To call across app domains you need to employ some kind of serialisation for your classes or inherit the class from MarshalByRefObject - see this SO question. Given that this looks like a proof of concept type of thing/a ground up implementation of your class then MarshalByRefObject would be you best bet - easiest i think. That said executing across AppDomains can get fiddly.
Invoking a method via instaniation in code
DivisionClass divisor = new DivisionClass()
divisor.Division(1,2)
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.
I am writing a (very small) framework for checking pre- and postconditions of methods. Entry points are (they could be easily be methods; that doesn't matter):
public static class Ensures {
public static Validation That {
get { ... }
}
}
public static class Requires {
public static Validation That {
get { ... }
}
}
Obviously, checking the postconditions may be expensive, and isn't actually necessary, when the method isn't buggy. So I want a method which works like this:
public static class Ensures {
[ConditionalCallingCode("DEBUG")]
public static Validation ThatDuringDebug {
get { ... }
}
}
where ConditionalCallingCodeAttribute means that this method should only run when the calling code is compiled with the DEBUG symbol defined. Is this possible?
I want client code to look like this:
public class Foo {
public void Bar() {
... // do some work
Ensures.That // do these checks always
.IsNotNull(result)
.IsInRange(result, 0, 100);
Ensures.WhileDebuggingThat // only do these checks in debug mode
.IsPositive(ExpensiveCalculation(result));
return result;
}
}
Of course, I can simply not provide WhileDebuggingThat. Then the client code would look like this:
public class Foo {
public void Bar() {
... // do some work
Ensures.That // do these checks always
.IsNotNull(result)
.IsInRange(result, 0, 100);
#ifdef DEBUG
Ensures.That // only do these checks in debug mode
.IsPositive(ExpensiveCalculation(result));
#endif
return result;
}
}
This is the fallback plan if nothing else works out, but it breaks DRY really badly.
As I understand it, marking WhileDebuggingThat with [Conditional("DEBUG")] will emit (or not) this method depending on whether DEBUG is defined during the compilation of the library, not of the assemblies which reference this library. So I could do this and then write documentation telling the library users to link debug builds of their code with the debug build of the library, and release builds with release builds. This doesn't strike me as the best solution.
Finally, I could tell the library users to define this class inside their projects:
using ValidationLibrary;
public static class EnsuresWhileDebugging {
[Conditional("DEBUG")]
public static Validation That() {
return Ensures.That;
}
}
This should work as well, as far as I see, but still requires breaking the DRY principle, if only slightly.
Is this anything that the normal ConditionalAttribute doesn't do for you, aside from working on a property instead of a method? You may well need to change the way things are called so that you've got methods instead of properties - and the fact that it returns a value may cause issues.
It would help a lot if you'd show how your framework is used - currently we've not got a lot to work with.
Another thing to consider would be supplying a variety of binary builds of your library - so that the caller can just supply a different version which doesn't actually do any checking. Again though, it's hard to tell with only the code you've provided.
Any solution that is found here would be slower than the actual checks. Also, since it would not be build into the compiler like ConditionalAttribute, the parameters would still be calculated. If the postconditions could be very complicated, such as
Ensures.That.IsPositive(ExpensiveCalculation(result));
You might consider using icelava's suggestion to reflect on the calling assembly to find if it is built in debug or release - but then you must use some sort of delegate to delay the calculation - to ensure that it is only done when needed. e.g.:
Ensures.WhileDebugging.That. IsPositive(() => ExpensiveCalculation(result));
The IsPositive function should run the lambda and check its result, only after reflecting to find out if it should be calculated.
I have not tried this since I am gonna bathe and leave the house.
Call Assembly.GetCallingAssembly() to get the assembly where the method (class) calling your current executing method comes from.
Run a check on that Assembly object to see if it is Release or Debug build.
It sounds like most of what you're doing is already covered using Debug.Assert().
For that matter, this code would only ever run in debug mode (but you have to put up with catch-block slowness):
try
{
Debug.Assert(false);
}
catch (Exception e)
{
// will only and always run in debug mode
}
It appears that what I want is just not available. I will probably settle for providing an implicit conversion from Validation to bool, so that validation checking may be wrapped in Debug.Assert().
The Debug Assert method can be set/changed using a bool even after the program is compiled, if for example the value is taken from a project user seting:
Debug.Assert(!Properties.Settings.Default.UseAutoDebug);
I'm not sure but I think you could use ConditionalAttribute for this: whether to emit call or not to emit will depend on type of build of user, not your library. You can check this with Reflector or ILDasm: compile your samples and in Reflector (ILDasm) look whether call is emitted or not in sample project.
I have this occur:
Project A call 1 function of B.
B include this function:
Assembly.GetCallingAssembly().FullName
If build B at mode debug then running, this function return name of Project A, if build at mode release than return name of project B.
I dont know reason of this occur.
Please support me
Thanks