I think I should be able to find something about this, but it seems I cannot.
I need to port a snippet of code that uses a missing overload of Activator.CreateInstance to .Net Standard 2.0.
string assembly = "My.Assembly";
string typeName = "My.Assembly.Something.MyType";
object newInstance = Activator.CreateInstance(assembly, typeName).Unwrap();
How could I replace this single line of code?
Please keep in mind that the assembly is not guaranteed to be loaded when the code is called.
Thanks!
Related
I'm using Pythonnet 2.4.0 to access a C# dll. I have a Windows 10 machine with Python 3.7.6.
I'm trying to use a method that only takes a path string as argument, but I don't manage to make it work.
import clr
sys.path.append(os.getcwd)
clr.AddReference('C#Wrapper')
path = "C:\\Users\\Username\\Folder"
c#class.method(string path)
If I use the overloads attribute from pythonnet, it tells me that the argument should be of type System.String, however doing something like below didn't help either:
path = System.String("C:\\Users\\Username\\Folder")
I keep getting a TypeError: No Method matches given arguments.
Do I need to encode the string or make a char array in order for c# to be able to understand it?
Edit:
I've just found a test function in the dll that only takes an Int32 argument and I have the same problem! I tried things like:
import ctypes
c#class.testmethod(ctypes.c_int32(1))
from System import Int32
c#class.testmethod(Int32(1))
but nothing worked. How can I pass arguments to the c# dll?
[Solved]:
I figured it out myself. In the second case I simply forgot to instantiate a class object. I should have done:
classobj = c#class()
classobj.testmethod(1)
This made me realize that in the first case I had basically the same issue. I followed a Visual Basic manual to write my Python program where it said something like this:
classobj = c#class
However in Python you need to write:
classobj = c#class()
So the missing parenthesis was causing the TypeError: No Method matches given arguments, which was very misleading. The type conversion and passing of arguments is perfectly handled thanks to the amazing developers of phythonnet! I won't delete this question in case other people experience the same issue.
The answer above is correct: Pythonnet passing arguments to c# dll.
I'd just like clarify what it means.
The error occurred because a method from a class was accessed without instantiating the object.
The solution is one of the two:
create an instance of the class
mark the .net method as static
The problem was that the error message is misleading, it says "No method matches given arguments". Which made me try to find the right argument.
By me this occurred when I forgot to add the static modifier to the .net method I called.
Is there any way to check if unity library exists in the project with scripts.
For example:
using UnityEngine.Advertisements;
And if it exists then make some actions like:
Advertisements.IsReady();
Thank you for your help!
Have a look at the MSDN documentation about the method Assembly.GetReferencedAssemblies(). This method returns an AssemblyName[] containing the names for all the assemblies referenced by this assembly. In other words the referenced assemblies are e.g. a library. Then you can easily wrap your a code in an if statement to either execute the code if your desired library (name) is contained in the array or to not execute.
Sample code:
Assembly currentAssembly = typeof(/*enter the class name which contains the assembly references*/).Assembly;
AssemblyName[] referencedAssemblies = currentAssembly.GetReferencedAssemblies();
foreach (var refAssembly in referencedAssemblies)
{
if (assembly == /*the name of the assembly you want to check that has to exist*/)
{
//...do your work if the assembly exists
break;
}
}
The technique behind this is called Reflection which I can highly recommend you to read about, its quite interesting.
You cannot use if else statement in this case because the compiler will complain about this, for example if(false) Advertisements.IsReady(); compiler cannot find type Advertisements.
But theres another way, you can use Reflection to get Type from the assembly. and then get the method to call, but still this is not the practical way.
You may want to use constant instead, or use ClassAttribute to tell that this script enable for advertisements, but using UnityEngine.Advertisements; is a must, you can create custom monobehaviour for this, and then inherit it to your application so that you can hide this line using UnityEngine.Advertisements;
I have an old .NET DLL which I have lost the source code to and I wanted to see if I could change its behavior.
It has a method that takes in a string and returns a string.
I would want to rewrite this method such that I can return
startStr + " test";
I tried .NET reflector but the project it produced has a bunch of strange errors so I cannot recompile it.
I then tried Reflexil, but it only offers assembly level changes.
Is there any way I could rewrite the method in C# and have the DLL use my method instead?
Reflexil should be able to handle this for you - you need to switch to IL view in Reflector and then you can go to the method that you want to change, pull up Reflexil and make your changes. This avoids the problems with decompiling the assembly to source code (which never worked for me without errors in Reflector).
If all you want to do is append a string to a string variable, you can just do something like:
// assuming your original string is already on the stack
ldstr " test"
call System.String System.String::Concat ( System.String, System.String )
This will create a new string on the stack with test appended to it. Once you're done with the editing, you can save the assembly back to disk.
If you need something more complicated (like appending a string returned by a function call), you simply need to call the right method and then call Concat() on the two strings on the stack.
If your original method returns a string then wrapping it in a new function in a new assembly may be a better solution, though. I'd only edit the IL if you really need the original assembly to change because - for example - the string returned from the particular method is used within that same assembly and you need other functions in that assembly to see the changed return value.
Note: I used Reflector 6.8.2.5 and Reflexil 1.0 for this - current Reflector / Reflexil may be different. Let me know if you need these files for your changes.
Have you tried extension methods? Simply add another method to an existing class.
You do this by:
public static class Foo {
public static String SomeMethod (this Bar bar) {
return bar.OriginalMethod()+" test";
}
}
If the original class was Bar.
I've never used .NET reflector, but you can try using the free decompiler offered by JetBrains, the makers of ReSharper, it has never failed me. http://www.jetbrains.com/decompiler/
On a side note, since you say that the dll is very old, couldn't the compilation errors in the Reflector generated project be produced by different versions of references or targeted framework?
I have the following problem:
public class MyType
{
public void method(int a, params object[] p){}
public void MyType()
{
method(5);
}
}
When I use a constructor everything is fine but when I try to use Activator.CreateInstance(MyType);
void Factory()
{
string componentPath = "MyType.dll";
Assembly component = Assembly.LoadFrom(componentPath);
Type myType= component.GetType("MyType");
Activator.CreateInstance(myType);
}
it fails with exception MyType.method(int32) is not found.
Important to notice that before I added params object[] p to method everything worked fine.
Thank You.
If you use methods with optional parameters or methods with params to pass a variable number of parameters, what you're doing is telling the compiler that when you CALL that method, will it please insert the necessary parameters for you? Optional parameters and params arrays are inserted in the calling code, not the called code. (See one of Eric Lipperts blog posts on optional parameters for some elaboration).
You're not using the C# compiler, and the Reflection API does not insert those parameters for you. For example, you can test this not just by reflection, but also by using two assemblies: Assembly A declares method(int X); it is compiled and the dll is referenced by assembly B. This assembly B contains a call to method(42). This works fine! Now, if you recompile assembly A and change the signature to method(int X, object bla=null) or method(int X, params object[] blas), then assembly B stops working - it contains an invalid call. Even so, the source code to assembly B is still OK - you just need to recompile.
Reflection simply happens not to do any of the optional parameter magic for you. It could, certainly - but it doesn't. While reflection doesn't support this, the DLR does, which brings me to the following...
Workaround: Try using the C# keyword dynamic, if possible (which for constructors, it isn't AFAIK) - that attempts to emulate C# calling conventions more closely and supports stuff like optional and named parameters. You may need to change the way your API is set up, however to use methods rather than constructors. It's hard to give more precise advice without seeing actual code.
Alternatively: You may be trying to load plugins, by the looks of it. .NET has some premade infrastructure to help you with this: Add-ins and Extensibility, which may make your task easier.
(Note: your example code is incomplete - I'm making a slight guess that method is in reality a constructor, but you should really post the actual code or at least a snippet that actually fails).
This won't work because you have to pass at least 2 parameters in your call to method(). The params modifier doesn't mean "optional".
It probably isn't even possible to do this, but I will ask anyway.
Is it possible to create a function that receives a string and then uses it as a right side argument for the goes to operator (=>) used in lambda?
Actually, what I want to do is to be able to redefine an specific method of a specific class during runtime. I want to be write down a function with the program running and attaching it to a delegate. Is it possible?
You have several ways how to do it:
dynamically create lambda expression (look at Dynamic LINQ: Part 1)
dynamically create CodeDom model and compile it at run-time (look at CodeDom.Compiler namespace
dynamically create C#/VB.NET source code and compile it at run-time (look at CSharpCodeProvider and VBCodeProvider classes )
dynamically create object model, which can do same things like the method (look at Strategy Design Pattern
The easiest way to do it is probably DLINQ as TcKs suggested.
The fastest (I believe, in 3.5) is to create a DynamicMethod. Its also the scariest method as well. You're essentially building a method using IL, which has about the same feel as writing code in machine language.
I needed to do this to dynamically attach event handlers in some thing or another (well, I didn't need to do it, I just wanted to make unit testing events easier). It seemed a bit daunting at the time because I don't know crap about IL, but I figured out a simple way to accomplish this.
What you do is create a method that does exactly what you want. The more compact the better. I'd provide an example if I could figure out exactly what you're trying to do. You write this method in a class within a DLL project and compile it in release mode. Then you open the DLL in Reflector and disassemble your method. Reflector gives you the option of what language you wish to disassemble to--select IL. You now have the exact calls you need to add to your dynamic method. Just follow the example on MSDN, switching out the example's IL for your reflected methods' code.
Dynamic methods, once constructed, invoke at about the same speed as compiled methods (saw a test where dynamic methods could be called in ~20ms where reflection took over 200ms).
Your question is pretty unclear, but you can certainly use expression trees to create delegates dynamically at execution time. (There are other ways of doing it such as CodeDOM, but expression trees are handier if they do all you need. There are significant restrictions to what you can do, however.)
It's often easier to use a lambda expression with some captured variables though.
For example, to create a function which will add the specified amount to any integer, you could write:
static Func<int, int> CreateAdder(int amountToAdd)
{
return x => x + amountToAdd;
}
...
var adder = CreateAdder(10);
Console.WriteLine(adder(5)); // Prints 15
If this doesn't help, please clarify your question.
Not that I am recommending this over the other better options, but there is a 7th method and thats to use AssemblyBuilder,ModuleBuilder,TypeBuilder, and MethodBuilder in the System.Reflection.Emit namespace to create a dynamic assembly. This is the same similar voodoo as using DynamicMethod.
For example you could use these to, at runtime, create a proxy class for a type and override virtual methods on that type.
To get you started here is some code...
using System;
using System.Reflection;
using System.Reflection.Emit;
var myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("Test"), AssemblyBuilderAccess.RunAndSave);
var myModule = myAssembly.DefineDynamicModule("Test.dll");
var myType = myModule.DefineType("ProxyType", TypeAttributes.Public | TypeAttributes.Class,
typeof(TypeToSeverelyModifyInAnUglyWayButItsNecessary));
var myMethod = myType.DefineMethod("MethodNameToOverride",
MethodAttributes.HideBySig | MethodAttributes.Public,
typeof(void),Type.EmptyTypes);
var myIlGenerator = myMethod.GetILGenerator();
myIlGenerator.Emit(OpCodes.Ret);
var type = myType.CreateType();
Use .net core 3.1, you can create dynamic method with IL language(mono is same as well):
using System.Linq.Expressions;
using System.Reflection.Emit;
class Program
{
static void Main()
{
DynamicMethod hellomethod = new DynamicMethod("WriteLine", typeof(void), new[] { typeof(string) }, typeof(Program).Module);
ILGenerator il = hellomethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
il.Emit(OpCodes.Ret);
Action<string> hello4 = (Action<string>)hellomethod.CreateDelegate(typeof(Action<string>));
hello4("Hello World!");
}
}
If you declare the method as virtual, you might be able to use Castle's DynamicProxy to substitute a dynamically-generated (with one of the other answer's methods) implementation at runtime:
Castle DynamicProxy is a library for generating lightweight .NET proxies on the fly at runtime. Proxy objects allow calls to members of an object to be intercepted without modifying the code of the class. Both classes and interfaces can be proxied, however only virtual members can be intercepted.
The second paragraph in your question suggests that really what you might be after is straightforward IOC (Inversion of Control)
Instead of declaring an instance of your class, you declare an instance of an interface and based on whatever condition you choose, you use the particular overriding class with the correct method in it. Hope that makes sense.
You should check to see if your problem can be solved with simple polymorphism first. Unless you're defining abstract interoperability to another language or editing the compiler, trying to change a method at runtime is probably the wrong solution to the problem.