.Net arbitratry runtime class instantion and method calling - c#

I am looking for a way to do arbitrary class instantion as well as attribute assignement and possibly method calling in .Net and preferrably C#. Since arbitrary is too broad a word let me tell you what I am after.
Let's say I have a DLL (objects.dll) that contains:
public class Person
{
// Field
public string name;
// Constructor that takes no arguments.
public Person()
{
name = "unknown";
}
// Constructor that takes one argument.
public Person(string nm)
{
name = nm;
}
// Method
public void SetName(string newName)
{
name = newName;
}
}
public class Table
{
// Field
public int width;
public int lenth;
public int height;
// Constructor that takes no arguments.
public Table()
{
width = 0;
length = 0;
height = 0
}
// Constructor that takes three arguments.
public Table(int w, int l, int h)
{
width = w;
length = l;
height = h;
}
// Method
public void SetWLH(int w, int l, int h)
{
width = w;
length = l;
height = h;
}
}
public class Printer
{
public Printer(){}
public void printAPerson(Person p)
{
//do stuff with p
}
public void printATable(Table t)
{
// do stuff with t
}
}
I want to be able to instantiate either of the classes above, set attribute values and call methods at runtime from a different program in the most generic possible. eg. lets say I hame a programm called myprog.exe, i want to be able to do the following
myprog.exe objects.dll Person name testname Printer printAPerson
where:
objects.dll is the dll that contains all required classes
Person is the first I will instantiate name is its attribute
testname is the value I will assign to this attribute
Printer is the class I will use for printing
printAPerson is the method in the Printer class I need to call with the specified object as a parameter.
As you can see, in the best case for my use scenario, neither of the objects and classes are/will be known at compile time so I would like to be as non-casting as possible. If that is not possible I will take what I can.
I have seen this, How to use reflection to call a method and pass parameters whose types are unknown at compile time?, which to my limited knowledge kind of does what I want minus the casting bits or I could be mistaken.
Thanks a lot!

Instead of using Reflection you could use dynamic. But this requires that the Printer class and others are changed. And you would loose intellisense and compile time checks.
public class Printer
{
public Printer() { }
public void printAPerson(dynamic p)
{
//do stuff with p
Console.WriteLine("Person name: " + p.name);
}
public void printATable(dynamic t)
{
// do stuff with t
Console.WriteLine("printATable(Table p) is called");
}
}
public class TestDynamic
{
public static void Test()
{
// To get the type by name,
// the full type name (namespace + type name) is needed
Type personType = Type.GetType("StackOverflowCodes.Person");
object personObj = Activator.CreateInstance(personType);
// Implicit cast to dynamic
dynamic person = personObj;
person.SetName("Alan Turing");
Type printerType = Type.GetType("StackOverflowCodes.Printer");
object printerObj = Activator.CreateInstance(printerType);
dynamic printer = printerObj;
printer.printAPerson(personObj);
}
}

Are you flexible concerning your executable input format? If so, you could do what you want by having a convention. I would do this using a JSON structure like this one:
{
Command : "",
Arguments : {
Argument1 : 0,
Argument2 : { }, // can be another complex object
Argument3 : [] // an empty array maybe ...
}
}
Where Command would be something like "ClassName.MethodName", Arguments will be a JSON object that each object property represents your method parameter.
In your executable, you must parse this JSON using a library (example http://www.newtonsoft.com/json) and use reflection to deserialize every JSON object parameter and call your method. If you cannot get it work, please let me know I will try to make an example (if I will have time, this night because I am at work right now).
For your case you just want to print an object of type Person to the printer right? You could execute a command like this:
{
Command : "Printer.PrintAPerson",
Arguments : {
p : { name : 'george' }
}
}
If you want to rely on a standard protocol, please check the JSON-RPC protocol: http://json-rpc.org/wiki/specification

Related

C# - How to get the value of a passed lambda expression

I have a special case. I need to rewrite a library and I do not have the original code. To make the discussion clearer lets call the library HandlerLibOld and HandlerLibNew.
I want to make HandlerLibNew that shall replace HandlerLibOld.
I have an application that uses this library, and it is big application with 1000s of calls to the library.
I rather not have to change the application code.
Sample application code
public class MyMessage : MyBaseClass
{
public int ValueA {get;set;}
public int ValueB {get;set;}
}
public class MyOtherMessage : MyBaseClass
{
public int ValueC {get;set;}
public int ValueD {get;set;}
}
public class Sender
{
Handler handler = new Handler();
handler.Send<MyMessage>(m => { m.ValueA=10; m.ValueB=20; });
}
Notice the line handler.Send<MyMessage>(m => { m.ValueA=10; m.ValueB=20; });. It uses a lambda expression to define an object of the MyMessage and sets two properties of this object. Notice that I rather not have to change this code.
Maybe I have misunderstood what the lambda expression does, but the point is I need to tell the Handler.Send about the values ValueA and ValueB.
Now I want to write the implementation of the Send method of the Handler. The tricky part is that the lambda expression makes it an action, but I want to get the MyMessage object instance. How can I achieve that? Do I need to use reflection somehow?
My attempts
I have tried:
public class Handler
{
public void Send<T>(Action<T> actionmessage)
{
// actionmessage is an object of type Action<T>,
// I want to get the object of type T that was passed into the method.
}
}
I have also tried:
public class Handler
{
public void Send<T>(T message)
{
// This will not compile. I get:
// Cannot convert lambda expression
// to type 'object' because it is not a delegate type
}
}
I know it is possible somehow because this works with the HandlerLibOld. How can I achieve the same with HandlerLibNew? I don't have access to the code of HandlerLibOld.
In order for that Action to work, you must have an instance of T to begin with:
public void Send<T>(Action<T> actionMessage)
where T: new()
{
var input = new T();
actionMessage(input);
//T has now valueA and valueB populated
//do more with input T
//send
}
Now if T were to have a constraint such as implementing a certain interface, you can do more stuff on the object itself. If you are using base classes you must be careful with object slicing.

Extension method not setting value

I have a product class that looks something like this -
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
}
I have an extension class that looks like this
public static class ProductExtension
{
public static void FixProduct(this Product product)
{
product = new Product(){Name = product.Name.ToUpper()};
//product.Name is now UPPERCASE
}
}
In my Main method I have -
static void Main(string[] args)
{
Product p = new Product() {ProductId = 1, Name = "steve"};
p.FixProduct();
System.Console.WriteLine(p.Name);
}
This prints "steve" and not what I wanted it to print: "STEVE".
Why doesn't the assignment in the extension method work?
I suggest a small change to follow a fluent interface pattern. Instead of void, return the new product instead. Don't use ref, that is weird.
public static class ProductExtension
{
public static Product FixProduct(this Product input)
{
return new Product
{
Name = input.Name.ToUpper(),
Id = input.Id
}
//product.Name is now UPPERCASE
}
}
Then use it like this:
static void Main(string[] args)
{
var p = new Product()
{
ProductId = 1,
Name = "steve"
}
.FixProduct();
System.Console.WriteLine(p.Name);
}
A neat advantage of this approach is (if you think you will need it) you can support several product classes while preserving their precise type, e.g.:
public static class ProductExtension
{
public static T FixProduct<T>(this T input) where T: Product, new
{
return new T
{
Name = input.Name.ToUpper(),
Id = input.Id
}
}
}
Now you could use it on any derived product class while keeping exactly the same syntax.
class DeluxeProduct : Product
{ }
static void Main()
{
var p = new DeluxeProduct
{
Id = 1,
Name = "Steve"
}
.FixProduct();
Console.WriteLine(p.GetType().Name)); //outputs "DeluxeProduct"
}
Now on the other hand, if all you want to do is "fix" the product's name, you could just wrap it in a property.
class Product
{
private string _name;
public int Id { get; set; }
public string Name
{
get { return _name; }
set { _name = value.ToUpper(); } //Automatically "fix" it the moment you set it
}
}
...and then you don't need an extension method at all.
Extension methods cannot be used that way. In your method you create a new instance of Product and then assign it to product which is a local reference to the passed object, and not the original reference p.
When you first enter the function what you have is two references referencing the same object in memory.
Then just before exiting the method you have two objects, one referred by each reference, with the product reference, referencing a local variable being cleaned by the GC at the end of the method call.
Solutions:
To correct this and have it closest to what you were trying to do,
change your method to get a ref parameter:
public static void FixProduct(ref Product product)
{
product = new Product() { Name = product.Name.ToUpper() };
//product.Name is now UPPERCASE
}
and then:
ProductExtension.FixProduct(ref p);
I believe a better approach all together will be (by having it a
member function or an extension method) to update the object instead
of instantiating a new one:
public static void FixProduct(this Product product)
{
product.Name = product.Name.ToUpper();
}
In your extension method, you are assigning a new Product to the variable product. This doesn't end up affecting the original referenced Product.
Modify the method to the one below to set the name on the original passed in object.
public static void FixProduct(this Product product)
{
product.Name = product.Name.ToUpper();
}
Parameters are passed by value unless they are ref or out. this doesn't change that. You can understand this syntactically because ref and out require a variable reference; otherwise only an expression is required.
Unfortunately, you can't combine this with ref or out.
You can change the value of any parameter variable, though, except in the case of ref or out, it's best avoided or limited to quick touch-ups to the passed-in value that simplify later algorithmic code.
A method is permitted to assign new values to a value parameter. Such
assignments only affect the local storage location represented by the
value parameter—they have no effect on the actual argument given in
the method invocation.
— C# Language Specification
So, the assignment does work, just not in the ref or out way.

For what do you need "this." in c# [duplicate]

This question already has answers here:
When do you use the "this" keyword? [closed]
(31 answers)
Closed 5 years ago.
The older apprentices in my company use "this." a lot.
Two weeks ago I started coding object-oriented and still don't get for what it is being used.
You need to understand what instance is first. Let's say you have an object:
public class House
{
public decimal Height { get; set; }
}
You can have multiple instances of it:
var smallHouse = new House { Height = 100M };
var bigHouse = new House { Height = 300M };
Each instance has its own value of Height. When you want to work with Height in a method of House, you need to refer to the current instance method is operating at (the one consumer called).
This can be done explicitly by using this as a special kind of variable that refers to this current instance:
public class House
{
public decimal Height { get; set; }
public bool IsItTooBig()
{
return this.Height > 200;
}
}
Or you can omit this and let C# guess that what you mean is the instance value:
public class House
{
public decimal Height { get; set; }
public bool IsItTooBig()
{
return Height > 200;
}
}
Programmers differ in opinion whether it's good or bad to be explicit there. If you follow capitalization conventions, you can distinguish instance state and method scope state (normal variables) by it.
There are cases where you absolutely need it, for example when you have naming conflict, or when you want to return current instance from a method:
public class House
{
public decimal Height { get; set; }
public House AddFloor()
{
Height += 100;
return this;
}
}
You should consider applying immutability in many of these cases though.
The keyword 'this' represents the instance of an object used to explicitly call a method, field or property of that instance.
Commonly used when your private fields have the same name as the parameters in a given method:
private string name;
public void SetName(string name) {
this.name = name;
}
When you want to refer to instance field within that class you use this, it can be omitted but there are cases it can not be omitted.
public class InstanceClass
{
int field = 10;
public void Method()
{
int field = 0;
Console.WriteLine(field); // outputs 0
Console.WriteLine(this.field); // outputs 10 because "this" refers to field.
}
}
if there is no declared local variable that conflicts with field name, "this" can be omitted.
public class InstanceClass
{
int _field = 10;
public void Method()
{
int field = 0;
Console.WriteLine(field);
Console.WriteLine(_field); // prefixed with _.
// no conflicts
// so "this" can be omitted.
}
}
another case where you can not omit this, is when you use indexer.
public class InstanceClass
{
private List<int> _source;
private int offset;
public int this[int index] // you use "this"
{
get => _source[index + offset]
set => _source[index + offset] = value;
}
public void Method()
{
var first = this[0]; // must use "this" to refer to indexer for this class.
}
}
"this" is used for calling constructor overloads too.
public class Foo
{
public Foo() : this(0)
{
Console.WriteLine("world");
}
public Foo(int param1)
{
Console.WriteLine("Hello");
}
}
//...
var foo = new Foo(); // outputs "Hello world"
"this" also refers to instance of class itself. so if you want to return instance of self you use this.
public class Foo
{
public Foo ReturnMe() // weird example.
{
return this;
}
}

Create class that creates another class that can be overloaded (like excel - Thisworkbook.Worksheets)

In Excel object model 'Thisworkbook' is a class that has 'Worksheets' class in it and can be overloaded with index or by sheet name. Moreover, 'Worksheets' class also has some properties/methods that can be called with/without calling the constructor (default).
E.g. MsgBox ThisWorkbook.Worksheets(1).Name '<-- by (int)
E.g. MsgBox ThisWorkbook.Worksheets("Sheet1").Name '<- by (string)
E.g. Msgbox Thisworkbook.Worksheets.Count '<- 'count property
How can I create such class in C# that has another class in it and can be overloaded?
I have tried creating a public variable of the 2nd class in the 1st class but I can only call default constructor (or other - but just one at a time)
class A
{
public B b = new B(); // <-- this is 1st constructor but how to overload ?
}
class B
{
public B() // Default Constructor
{
}
public B(int i) // Constructor 2
{
}
public B(string s) // Constructor 3
{
}
public int Count // Property
{
get { return 0; }
}
}
//------------------------------------------------------------
class Main()
{
A a = new A();
a.b.Count(); // <-- THIS WORKS
// a.b(1).Name; <-- HOW TO, USING THE SAME CLASS?
// a.b("A").Name; <-- HOW TO, USING THE SAME CLASS?
}
I know that I have not created an object array - 1 or "A" that can be returned in this example, but I just need the concept (you got it right?). I have also seen few examples using List but I really want to know how I can achieve such object hierarchy in C#... (please excuse me if this is a wrong question).
You're misunderstanding operators.
What you're seeing is the indexing operator defined on the Worksheets class.
In C#, that would be called as a.b[1] or a.b["2"].
You define it like this:
public SomeType this[int index] { get { ... } }
public SomeType this[string index] { get { ... } }

How do I get the value of the used parameters in a constructor (C#)

I've got a question about getting the values from a constructor in a generic way.
namespace myTestNamespace
{
Public Class myTestClass()
{
Public myTestClass(int myInt,bool myBool, double myDouble)
{
//do / set something
}
Public myTestClass(int myInt,bool myBool)
{
//do / set something
}
}
}
Using (what you need);
Using myTestNamespace;
namespace MyIWannaLookForTheParametersName
{
Public Class MyLookUpClass()
{
Public void DoSomething()
{
List<object> myList = new List<object>();
myTestClass _ myTestClass = new myTestClass(1,true,2.5);
object mySaveObject = myTestClass;
mylist.Add(mySaveObject);
//how do I get the info from the right constructor
//(I used the one with 3 parameters_
//what was the value of myInt, myBool and myDouble
//how can I make it generic enough, so it will work with other classes with
// different constructors ass well?
}
}
}
Questions about intent aside, there's no generic way for you to do this. Information about what methods have been called and what values were supplied is not saved automatically. You are, of course, perfectly able to keep track of these things yourself, but you would have to write each class to do this explicitly.
Doing this in a generic way is asking for trouble. What if I did this?
public class Foo
{
public string Name { get; set; }
}
public class Bar
{
public Bar(Foo foo)
{
// ...
}
}
Then suppose I called it in this way:
Foo f = new Foo();
f.Name = "Jim";
Bar b = new Bar(f);
f.Name = "Bob";
Now, if such a generic system existed, what would be the value of foo for the Bar constructor? Either it reports "Bob" (which is what the value for Name is on the instance of Foo that was supplied), or it reports "Jim", meaning that the runtime or library would essentially have to be smart enough to make a deep copy of the object so that the state is not changed.
The bottom line is this: if you need access to the parameters passed to the constructor (or any other function), you'll have to store them somewhere explicitly.
You can't get thevalues from the constructor. You need to first place them in a property or a field within your class. The example you provided is a poor use of generics. You wouldbe better off placing the constructor values into properties and creating an interface with those properties.
I got what I needed with this method:
private static ParameterSettings[] GetListOfParametersFromIndicator(object indicatorClass, int loopId, myEnums.ParaOrResult paraOrResult)
{
return (from prop in indicatorClass.GetType().GetProperties()
let loopID = loopId
let Indicator = indicatorClass.GetType().Name
let value = (object)prop.GetValue(indicatorClass, null)
where prop.Name.Contains("_Constr_")
select new ParameterSettings { ParaOrResult=paraOrResult, LoopID= loopId, Indicator= Indicator, ParaName= prop.Name, Value= value }).ToArray();
}
where ParameterSettings is:
public struct ParameterSettings
{
public myEnums.ParaOrResult ParaOrResult { get; set; }
public int LoopID { get; set; }
public string Indicator { get; set; }
public string ParaName { get; set; }
public object Value { get; set; }
}
This info is ok for me. Thanks for the replies.
Regards,
Matthijs

Categories

Resources