Access to methods in Object type - c#

I'm trying to figure out how to do something like the following (that was typed off the top of my head so it might not be 100% accurate, but it should get the point across) in csharp, but I'm not really sure how.
class Test
{
private __construct() {}
public static function GetInstance($name)
{
if (file_exists($name . ".php"))
{
return new $name();
}
else
{
return null;
}
}
}
I know how to get the object I want back based on the input, but I have to return an Object, because I'm not sure which one the caller will request. However, when I have no idea how to get access to the methods in the returned Object.

Assuming I understand your pseudo code correctly you will have to cast the resulting object to the type that you are expecting so you can access the public methods of that type:
Foo myFoo = (Foo) Test.GetInstance("Foo");
string bar = myFoo.Bar();
Also check the Activator.CreateInstance() method which basically does what your GetInstance method wants to do.

If I interpret your question correctly I think you want to create an object by type name. There are a number of ways to do this. This is one example:
public static class Test
{
public object CreateInstance(string typeName)
{
Type type = Type.GetType(typeName);
return Activator.CreateInstance(type);
}
}
This assumes the typeName is a full type name including namespace, and that this type has a default (no argument) constructor. Otherwise the method will fail. Use for example like this (you have to cast to User your type in order to access the methods in the User type.
User user = (User)Test.CreateInstance("Some.Namespace.User");
// Now methods and propertes are available in user
Console.WriteLine("User name: "+user.Name);

Hope this thread also helps. Here is some more reflection examples.
// create instance of class DateTime
DateTime dateTime = (DateTime)Activator.CreateInstance(typeof(DateTime));
// create instance of DateTime, use constructor with parameters (year, month, day)
DateTime dateTime = (DateTime)Activator.CreateInstance(typeof(DateTime),
new object[] { 2008, 7, 4 });

Related

Creating a generic method that accepts a type and returns an instance of that type [duplicate]

This question already has answers here:
How to create a new object instance from a Type
(11 answers)
Closed 1 year ago.
I want to pass a Type to a method and have the method create and return a new variable of that type. I need the new variable to be instantiated with it's default value rather than pass back a null. While in the method I then need to save that instance in a list of object (not shown for clarity). My code below runs but I get a null as the return value. I expect an instantiated instance of that type that is not null. I will be using this method for multiple Types (string, double, List, ...etc). I am hoping there is a flexible way to do this rather than hardcoding for a new type each time I need a new type.
I do see this answer here. This looks like it is workable but only for one type (IPerson):
public string InstantiateType<T>(string firstName, string lastName)
where T : IPerson, new()
in the example in the question. I was hoping for a more generic solution workable for multiple types - string, double, List, ...etc. Whatever is passed to to the method.
I started with:
public static T DoSomeStuff<T>(string name)
{
T newVar = default;
//Do some stuff with newVar
return newVar;
}
I tried (and get null):
public static T DoSomeStuff<T>(string name) where T : List<string>
{
T newVar = default;
//Do some stuff with newVar
return newVar;
}
I created a question earlier today that was quickly closed as a duplicate. I did just find this answer that seems to work. Perhaps this is my answer?
public static T DoSomeStuff<T>(string name)
{
T newVar = Activator.CreateInstance<T>();
return newVar;
}
I started with ... default(T)
The default keyword in C# behaves differently depending on the type in question. Value types will use their default value (which may be the intended behavior); however, reference types' default value is null, which is not the intended behavior.
I tried (and get null) ...
Once again, default will not return an instance of type T when T is a reference type.
I did just find this answer that seems to work. Perhaps this is my answer?
You're right. Activator.CreateInstance() is the easiest way to create an instance of an arbitrary type. It's worth noting that that type must have a parameterless constructor (e.g. new MyClass()), or you must provide arguments for a valid constructor.
To enforce that Activator.CreateInstance() requires a parameterless constructor, you can constrain T to new():
public static T DoSomeStuff<T>(string name) where T : new()
{
T newVar = Activator.CreateInstance<T>();
return newVar;
}

Type manipulation

Is it possible to create a method which returns a type and use it?
for example, assume I have a Person type and Object parameter.
As you probably know, If we want to cast our Object parameter, we can write:
object param;
((Person)param).executePersonMethod();
My question is how can I write a method which return Person type and use it instead the concrete Person cast - I want write something like this:
public Type GetPersonType()
{
//return here type of person
}
and then use
((GetPersonType())param).executePersonMethod();
Is it possible?
If yes, how?
You can use interface.
((IPerson)param).executePersonMethod();
each type of person must be an IPerson
and in IPerson you declare executePersonMethod()
You can also use dynamic for this.
Note that using dynamic will skip any compile time checking whether that method exists and will throw an exception at runtime if it doesn't.
Due to this risk, I would only do this if I have no other choice, but it's good to know that the option exists:
dynamic d = param;
d.executeWhateverMethodHereWithoutCompileTimeChecking();
Yes you can. There is a new type called dynamic which will avoid static type check during compilation.
public dynamic GetPersonOrObjectWhichHasExecutePersonMethod()
{
//return not the type but the object itself
return new Person();
}
public class Person
{
public void executePersonMethod()
{
// do something
}
}
// this is how you invoke it
public void ExecuteMethod()
{
dynamic obj = GetPersonOrObjectWhichHasExecutePersonMethod();
obj.executePersonMethod();
}
Maybe you can use something like that:
Convert.ChangeType(param, typeof(Person));
It would returns param as a Person.
You cannot execute methods on a Type, you can only execute methods on an instance of a particular Type. If I am understanding correctly, you should be able to use the answer #LavG gives to:
return not the type but the object itself from the GetPersonType method
Edit: As per your comment:
Here are some SO QA which will help you get the Type using fully
qualified namespace and other techniques:
How to get the type for a class by sending just the name of the class instead of the class itself as the parameter?
Type.GetType("namespace.a.b.ClassName") returns null
Here is how to generate a class from the given Type at run time:
generating a class dynamically from types that are fetched at runtime
Use
TypeOf()
Example :
if (data.GetType() == typeof(Personne))
return (Personne)data;
else
return new Personne();
After, check your object is not null to know if it's ok
Although you can use Generic as a better option, however it is possible using Type Convertor in combination with reflection:
Type type = GetPersonType();
var converted = Convert.ChangeType(param, type);
converted
.GetType()
.GetMethod(/*your desired method name in accordance with appropriate bindings */)
.Invoke(converted, /* your parameters go here */);

Create new object from instance of another

Similar questions I have found, but I am still having troubles:
Dynamically create an object of <Type>
Get a new object instance from a Type
-- A better description of the problem, hopefully?----
When I call the web service, the response that is brought back is an xml document. That document defines the class that is being returned and then all the values are set through deserializing the xml into 1 of the 8 different types.
Now when I do receipt.Item I get the type that is returned; but because of the way the interface is set up with the web service call I can't access any of the items member variables unless I type cast receipt.Item. That is being done with the switch case. But I want the create the object outside of the switch case and initialize it inside the switch case so I can access it later in the code. That is why I do not create a new object of that type in the switch case and do my work there (or call a function).
I have an overarching return type of Response from a web service that I am calling and the web service can have 8 different result types. I need to create a instance of the 1 of the 8 return types that can be returned.
So here is the structure for a more visual purpose
Response
accountUpdaterRespType
endOfDayRespType
flexCacheRespType
The code for the response objects:
public partial class Response {
private object itemField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("AccountUpdaterResp", typeof(accountUpdaterRespType))]
[System.Xml.Serialization.XmlElementAttribute("EndOfDayResp", typeof(endOfDayRespType))]
[System.Xml.Serialization.XmlElementAttribute("FlexCacheResp", typeof(flexCacheRespType))]
public object Item {
get {
return this.itemField;
}
set {
this.itemField = value;
}
}
}
When I get the return object of Response I can get the type by doing responseObject.Item and do a GetType() on that. So that is what I have available to me to attempt to type cast a new object.
I have to do this because when I do responseObject.Item I don't have access to the different variables that are in the different object types. So I am trying to type cast a new object in a switch case like so:
object newReceipt = Receipt.GetType(); //this is where I would get the type I assume?? I don't know
string type = Receipt.Item.GetType().ToString();
switch (type)
{
case "accountUpdaterRespType":
newReceipt = (accountUpdaterRespType)Receipt.Item;
break;
case "endOfDayRespType":
newReceipt = (endOfDayRespType)Receipt.Item;
break;
case "flexCacheRespType":
newReceipt = (flexCacheRespType)Receipt.Item;
break;
}
I'll try to restate your question before answering it.
You're trying to create a typed reference to existing instance. You already have an instance of an object, held in a variable of type object, but want to cast it up in order to be able to access members.
By getting variable type in code, you still won't be able to access object members in development time.
Using strings to check object type is not a good idea. Working solution to your problem would be following
// as is a type of cast. if Receipt is of type cast,
// it will return an object and put it into accountUpdater
// variable. If Receipt is not of that type, it will place null
// into accountUpdater variable
var accountUpdater = Receipt.Item as accountUpdater;
if (accountUpdater != null)
{
// Do something with account updater here. E.g.
Console.WriteLine(accountUpdater.SomeAccountUpdaterProperty);
}
var endOfDayResp = Receipt.Item as endOfDayRespType;
if (endOfDayResp != null)
{
// Do something with endOfDayResp here
}
var flexCache = Receipt.Item as flexCacheRespType;
if (flexCache != null)
{
// Do something with flex cache here
}
You get the idea. Mind you, this is not a very nice way to write code. Example above is just to get you up and running. You should get acquainted with object-oriented programming concepts, and for this case particularly, polymorphism.
Another (essentially same) way to handle this would be:
var accountUpdater = Receipt.Item as accountUpdater;
if (Receipt.Item is accountUpdater)
HandleAccountUpdater((accountUpdater)Receipt.Item);
else if (Receipt.Item is endOfDayRespType)
HandleEndOfDay((endOfDayRespType)Receipt.Item);
else if (Receipt.Item is flexCacheRespType)
HandleFlexCache((flexCacheRespType)Receipt.Item);
else
throw new InvalidArgumentException("Unexpected parameter type");
You are correct, polymorphism is a solution in situations where objects have similar traits and need to be handled in similar fashion. Two solutions above are best way you can do without learning a little bit more about C# language. Second solution provides better separation of responsibilities.
You can get more generic solution using reflection. Using methods in System.Reflection you can make a more generic resolution of handler methods. Take following for example:
You have Response object such as you described. You also have a class which can handle different types of objects. For example:
public class ResponseHandler
{
public void Handle(accountUpdater parameter) { /* */ }
public void Handle(endOfDayRespType parameter) { /* */ }
public void Handle(flexCacheRespType parameter) { /* */ }
public void Handle(TypeD parameter) { /* */ }
public void Handle(TypeE parameter) { /* */ }
...
}
Once you receive response, you will be able to determine which handler to call dynamically, without adding each and every type manually, like so:
var handler = new ResponseHandler();
var handlerClassType = typeof(ResponseHandler); // This is how you get Type object from a type. Unlike, `GetType` on objects
var paramType = Response.Item.GetType();
// Get me method which is named Handle and takes parameters in parameter array
// handlerMethod will be of type MethodInfo. This is basically a descriptor of a
// method. Not a pointer to a method or some such...
var handlerMethod = handlerClassType.GetMethod("Handle", new Type[] { paramType });
// Throw exception if we don't know how to handle it
if (handlerMethod == null)
throw new Exception("Handler not found for received response type");
// Invoke the handler. We need to provide the method descriptor with object which
// should execute the method, and parameters that the method takes
handlerMethod.Invoke(handler, new object[] { Response.Item });
This is written here in SO editor, so it may not run right away :)
To expand on Nikola Radosavljević's first answer, you could create an extension method like this:
public static IfType<T>(this object o, Action<T> action) {
var asType = o as T;
if (asType != null) {action(asType);}
}
Then you could do the following, giving you design-time access to all the members of each specific type:
Receipt.Item.IfType<accountUpdater>(r => {
Console.WriteLine(r.SomeAccountUpdaterProperty);
});
Receipt.Item.IfType<endOfDayResp>(r => {
//Do something with endOfDayResp here
});
Receipt.Item.IfType<flexCacheResp>(r => {
//Do something with flexCacheResp here
});
Still a lot of noise, but a bit more concise.
To do this the OOP way, define an interface:
interface IResponseItem {
void DoAction();
}
Then, each item type should implement the IResponseItem interface:
public class AccountUpdater : IResponseItem {
private int data;
public void DoAction() {
Console.WriteLine(data);
}
}
Then, you define the type of Response.Item as IResponseItem, and you can call the DoAction directly, without knowing the actual (a.k.a. concrete) type of the item:
Response.Item.DoAction();
This is polymorphism - having a common base type (IResponseItem) with multiple inheriting/implementing types (AccountUpdater etc.) that implement the same member (DoAction) to do different things. (Polymorphism in the C# Programming Guide on MSDN)
Your problem could be solved with the implementation of either an interface or an abstract base class.
If a type implements other types, you can store in a lower typed variable. For instance, in .Net every type is derived from the basic class object. This is allows you to store a List, a String and every other type in a object variable.
Similar, you can use interfaces to store instances that implement that interface. A interface is basically a list of methods and properties that a class needs to implement.
In your case I'd suggest you should add a higher level of abstraction. For instance you could create a interface
interface IResponse {
int StatusCode {get;}
string Content {get;}
...
}
You could implement this interface in every response.
public class EndOfDayResponse : IResponse
{ ... }
The type of Receipt.Item would then be IResponse instead of object. You could then check the actual type with response is EndOfDayResponse and then do the appropriate casting.

Returning desired type from Activator.CreateInstance() instead of object

I'm trying to create an instance of specified Type whatever user wants to have. For a quick illustration of my purpose please see the code below:
static void Main(string[] args)
{
object o = GetInstance(typeof(int));
Console.WriteLine("Created type: {0}", o.GetType().FullName);
}
public static object GetInstance(Type t)
{
Console.WriteLine("Creating instance of {0}", t.FullName);
return Activator.CreateInstance(t);
}
The problem is Activator.CreateInstance() returns object by default. There is also an overload of this method like T Activator.CreateInstance<T>() which is parameterless and returns the type you specify as T.
However, the problem is T should be hard-coded while calling this method and thus should be a fixed value. I am trying to create an instance of desired class and return it as its type.
Right now if you use this method you should write something like:
int i = GetInstance(typeof(int)) as int
I'm trying to reduce this to:
int i = GetInstance(typeof(int))
Is there a way that I can do casting inside the GetInstance and get rid of that as int repetition? By this way, my return type (and also the type I cast the object to) will be unknown at compile time.
Seemed impossible by design to me but I'd really appreciate if you figure it out.
EDIT: Where I'm stuck is e.g. while you're casting, you can do return (T) result if you are in a generic method, but you can't do Type t = ...; return (t) result this doesn't work. You cannot cast to a type which is passed to you as a parameter which is not known at compile time.
Follow a known pattern
This is not a new problem. It is a problem facing any API that allows type-specific return values. For example, a JSON parsing library like Newtonsoft (which is, to wit, the single most popular .NET package downloaded by .NET programmers in 2019) must be able to parse a string and return a type-specific object, which may or may not be known at compile time. It might make sense to follow their example.
Newtonsoft exposes three ways to specify the type when deserializing. You could do as you are currently doing:
//Cast required
var result = JsonConvert.DeserializeObject(text, typeof(MyType)) as MyType;
You can use a generic method:
//No cast required, but you have to hardcode a type as a type parameter
var result = JsonConvert.DeserializeObject<MyType>(text);
Or you can use an instance as a template, which is great for anonymous types, although you can use it with non-anonymous classes as well. This one works via generic type inference:
//No cast required and no need to specify type; the type is inferred from the argument
var result = JsonConvert.DeserializeAnonymousType(text, new MyType());
Here's how you'd do it:
So for you to make this work, your code might look like this:
public object GetInstance(Type type)
{
return Activator.CreateInstance(type);
}
int i = GetInstance(typeof(int)) as int;
public T GetInstance<T>()
{
return Activator.CreateInstance<T>();
}
int i = GetInstance<int>();
public T GetInstance<T>(T template)
{
return Activator.CreateInstance<T>();
}
int i = GetInstance(0);
If you do it this way, it's hard to imagine any programmer would have trouble using your library, as the approach should already be familiar to them.
Actually you could write GetInstance like this:
static T GetInstance<T>()
{
return Activator.CreateInstance<T>();
}
And use it:
int j = GetInstance<int>();
This might help you to create instance of desired type:
public class ConcreteFactory<T> : AbstractFactory<T>
{
public override T CreateInstance(string typeName,params object[] parameters)
{
var path = Assembly.GetExecutingAssembly().CodeBase;
var assembly = Assembly.LoadFrom(path);
var type = assembly.GetTypes().SingleOrDefault(t => t.Name == typeName);
return (T)Activator.CreateInstance(type, parameters);
}
}
Key here is generic type T can be used to cast the created instance, this can be used as a template to create instance of any type with parameterized constructor

C# reflection get object from type

I have a Type object.
I want to get the object isntance from this type. (just to use the ToString() method from this object).
see:
public class P
{
public string s;
}
class Program
{
static void Main(string[] args)
{
P p = new P();
p.s = "foobar";
Type t = p.GetType();
P p2 = ((t.ToObjet()) as P).s;
Console.WriteLine(p2.s);
}
}
Activator.CreateInstance is what you want.
Type givenType;
var obj = Activator.CreateInstance(givenType);
...
var obj = Activator.CreateInstance(givenType) as GivenType;
EDIT: Based on your edits, the extension method on Type you want (ToObject) is effectively the code above. It must create a new one because you can't be certain the source object still exists and even with the type, you could hit a scenario where that type has multiple instances.
You cannot get the instance back. The type is shared between all the instances, so what you want is impossible.
For example: if you know that something is an integer, you don't know which exactly value it has. (Integer is your type, value is a concrete instance.)
There is no way to do that. One reason is that GetType will return the same Type instance for all instances of the same type.
You can test this like so:
// this will print "True"
Console.WriteLine(object.ReferenceEquals("one".GetType(), "two".GetType()));
Calling GetType on those two different string instances returns the same Type instance, so it is clearly impossible to get one of them back based only on that Type instance.

Categories

Resources