A sample code I tried to return an instance of class is given below.
public object getConstructorclass(int i)
{
if(i==1)
{
Type type = Type.GetType("test1");
}else
{
Type type = Type.GetType("test2");
}
return Activator.CreateInstance(type);
}
var objcls = getConstructorclass(1);
objcls.callclass();//error occured
How can I mention the class type here since the type is not known at compile time but it will decided at runtime.In the above example i just pass a value 1 (it can be anything and that class will be called accordingly), and the class test1 called.
here I will get an error on the line objcls.callclass(), because objcls is an object instance that doesn't have a callclass()method.
How can I restructure this piece of code? My aim is if I mention a class in the getConstructorclass() method, an object should be returned so as to use it in the further code to invoke the members of that class.
If you know that your classes will have this method, you should use a common interface for them and implement it accordingly. Then you will work with classes that you have made sure it will work.
It would look like this
IMyInterface objcls = getconstrorclass() as IMyInterface;
if (objcls != null)
objcls.callclass();
else
// we failed miserably and should do something about it
I don't think you should use some generic object returning constructor based on an int variable, if your classes don't have anything in common. It's really weird to handle it like this and it may lead to various problems (some of which you're currently already experiencing). Generic class constructors make sense if the classes are somewhat related and you can predict the outcome, but to create a do-it-all method.. Not so sure about correctness of such approach.
Anyway, if you insist (not recommended, but as you wish), you can create some checks for a type like this:
var createdObject = getConstructorclass(1);
if (createdObject is MyClass1)
{
var specificObject = (MyClass1)createdObject;
specificObject.callMethod1();
}
else if (createdObject is MyClass2)
{
var specificObject = (MyClass2)createdObject;
specificObject.callSomeOtherMethod();
}
...
But it gets very error prone soon, refactoring will probably be a nightmare etc., but it's your call..
Or you maybe can use solution from pwas, but to me it seems unnecessarily complicated for such a basic task. Looks nice and all, but it still returns only the type "object", so it doesn't really solve your specific problem.
Also, to address one issue I'm not sure you understand - you've already created the instance, you just return type object. That is why you can't call any specific methods on this object, because first you have to cast it to something, that actually has that method and make sure the cast can be done (inheritance etc).
If interface solution (see other answers) is enough, don't look at this answer. When you can't use common base class / interface and you still want call members, you can use solution with is keyword (and check types). Instead of writing many ifs for each case, you can use fluent API:
object obj = this.getConstructorclass();
obj.StronglyInvoke()
.When<int>(value => Console.WriteLine("Got {0} as int", value))
.When<string>(value => Console.WriteLine("Got {0} as string", value))
.OnFail(() => Debug.Write("No handle."))
.Invoke();
Solution:
public class GenericCaller
{
private IList<GenericInvoker> invokers = new List<GenericInvoker>();
private readonly object target;
private Action failAction;
public GenericCaller(object target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
this.target = target;
}
public GenericCaller OnFail(Action fail)
{
this.failAction = fail;
return this;
}
public GenericCaller When<T>(Action<T> then)
{
if (then == null)
{
throw new ArgumentNullException("then");
}
var invoker = new GenericInvoker<T>(this.target, then);
this.invokers.Add(invoker);
return this;
}
public void Invoke()
{
if (this.invokers.Any(invoker => invoker.Invoke()))
{
return;
}
if (this.failAction == null)
{
throw new InvalidOperationException("Handler not found");
}
this.failAction();
}
public abstract class GenericInvoker
{
protected readonly object target;
protected GenericInvoker(object target)
{
this.target = target;
}
public abstract bool Invoke();
}
public class GenericInvoker<T> : GenericInvoker
{
private readonly Action<T> then;
public GenericInvoker(object target, Action<T> then)
: base(target)
{
this.then = then;
}
public override bool Invoke()
{
if (this.target.GetType() == typeof(T))
{
this.then((T)this.target);
return true;
}
return false;
}
}
}
public static class Extensions
{
public static GenericCaller StronglyInvoke(this object o)
{
return new GenericCaller(o);
}
}
Remeber - it would be more elegant to use common interface (as other answers say) - my is only alternative way.
Declare your variable as dynamic
dynamic objcls = getconstrorclass();
Using this the will be determined at run-time, whatever the getconstrorclass method returns. You can access any member of the type and you won't get any error at compile-time. But if you try to access a member which doesn't exists you will get a RuntimeBinderException at runtime.
I would recommend using an interface and restricting the classes that you can instantiate this way to only those that implement the interface.
public interface IMyInterface
{
void callclass();
}
public <T> getConstructorClass()
{
T instance;
Type type = Type.GetType("test1");
// instance will be null if the object cannot be cast to type T.
instance = Activator.CreateInstance(type) as T;
return T;
}
IMyInterface objcls = getConstructorClass<IMyInterface>();
if(null != objcls)
{
objcls.callclass();
}
not sure what you want to achieve in the end, but this looks like a job for "Dependency Injection" - here is a nice sample using autofac
Related
EDIT: changed Activator, still doesn't work.
So I'm pretty (very) new to C# and I'm pretty sure this is a dupe, but I've looked through the previous questions and I still can't work out all the points.
I am trying to reduce code smell by replacing some repeated code with a map over a generic list. Specifically, I have code that looks like
var fooNode = node as IFoo;
var barNode = node as IBar;
var bazNode = node as IBaz;
...
if(fooNode != null)
return new FooThing();
if(barNode != null)
return new BarThing();
if(bazNode != null)
return new BazThing();
...
and I want to generalise it.
Here's my attempt:
var types = new Dictionary<Type, Type>
{
{typeof(IFoo), typeof(FooThing)},
{typeof(IBar), typeof(BarThing)},
...
}
foreach(var entry in types)
{
var castNode = node as entry.Key;
return Activator.CreateInstance(entry.Value);
}
Naturally, it doesn't work: The type or namespace name 'entry' could not be found (are you missing a using directive or an assembly reference?). Can you help? Is this sort of thing even possible in C#?
How about this?
foreach(var entry in types)
{
if (node != null && entry.Key.IsAssignableFrom(node.GetType()))
{
return Activator.CreateInstance(entry.Value);
}
}
The problem is that you are confusing generic type parameters with runtime types and in particular the Type class.
If you know what a type will be at compile time then you can use the generic Activator.CreateInstance<T>() method to create an instance of the underlying object - you can use things like type parameters so that this line of code doesn't need to know what the type is, for example:
T CreateObject<T>()
{
return Activator.CreateInstance<T>();
}
However this just passes the buck. In order to call this method the value of the type parameter T must be supplied somewhere - either way the compiler must be able to resolve T to a type (rather than a variable or method).
Conversely the Type class encodes type information at runtime such as its name or the assembly that a type is declared in. Activator.CreateInstance also comes with an overload that allows you to supply an instance of Type:
object CreateObject(Type type)
{
return Activator.CreateInstance(type);
}
In your case it looks like you don't know what the types will be at compile time, so you will be mostly working with the Type class - you can use typeof(MyClass) to get an instance of the the corresponding Type for a class known at runtime, and myObject.GetType() to get type information for an object at runtime.
var types = new Dictionary<Type, Type>
{
{typeof(IFoo), typeof(FooThing)},
{typeof(IBar), typeof(BarThing)},
...
}
foreach(var entry in types)
{
if(entry.Key.IsAssignableFrom(node.GetType()))
return Activator.CreateInstance(entry.Value);
}
return null;
Without understanding clearly your purpose for wanting to return different types from the same operation it will be hard to help. Maybe a little background information into the problem you are trying to solve??
I will assume that since you are attempting to return them interchangeably that fooThing, BartThing and BazThing have the same interface. So I am assuming the following:
public class FooThing : IMyOperations
{
}
public class BarThing : IMyOperations
{
}
public class BazThing : IMyOperations
{
}
You can define the relationship between the classes in another interface
public interface IMyChoice
{
public bool IsSelected { get; }
public IMyOperations GetWorker();
}
public class ChoiceFoo : IMyChoice
{
}
public class ChoiceBar : IMyChoice
{
}
public class ChoiceBaz : IMyChoice
{
}
Now you can say
foreach( var entry in choices)
{
if(entry.IsSelected)
{
return entry.GetWorker();
//Can't remember if i need to break after return..doubt it
}
}
I asked a question yesterday regarding using either reflection or Strategy Pattern for dynamically calling methods.
However, since then I have decided to change the methods into individual classes that implement a common interface. The reason being, each class, whilst bearing some similarities also perform certain methods unique to that class.
I had been using a strategy as such:
switch (method)
{
case "Pivot":
return new Pivot(originalData);
case "GroupBy":
return new GroupBy(originalData);
case "Standard deviation":
return new StandardDeviation(originalData);
case "% phospho PRAS Protein":
return new PhosphoPRASPercentage(originalData);
case "AveragePPPperTreatment":
return new AveragePPPperTreatment(originalData);
case "AvgPPPNControl":
return new AvgPPPNControl(originalData);
case "PercentageInhibition":
return new PercentageInhibition(originalData);
default:
throw new Exception("ERROR: Method " + method + " does not exist.");
}
However, as the number of potential classes grow, I will need to keep adding new ones, thus breaking the closed for modification rule.
Instead, I have used a solution as such:
var test = Activator.CreateInstance(null, "MBDDXDataViews."+ _class);
ICalculation instance = (ICalculation)test.Unwrap();
return instance;
Effectively, the _class parameter is the name of the class passed in at runtime.
Is this a common way to do this, will there be any performance issues with this?
I am fairly new to reflection, so your advice would be welcome.
When using reflection you should ask yourself a couple of questions first, because you may end up in an over-the-top complex solution that's hard to maintain:
Is there a way to solve the problem using genericity or class/interface inheritance?
Can I solve the problem using dynamic invocations (only .NET 4.0 and above)?
Is performance important, i.e. will my reflected method or instantiation call be called once, twice or a million times?
Can I combine technologies to get to a smart but workable/understandable solution?
Am I ok with losing compile time type safety?
Genericity / dynamic
From your description I assume you do not know the types at compile time, you only know they share the interface ICalculation. If this is correct, then number (1) and (2) above are likely not possible in your scenario.
Performance
This is an important question to ask. The overhead of using reflection can impede a more than 400-fold penalty: that slows down even a moderate amount of calls.
The resolution is relatively easy: instead of using Activator.CreateInstance, use a factory method (you already have that), look up the MethodInfo create a delegate, cache it and use the delegate from then on. This yields only a penalty on the first invocation, subsequent invocations have near-native performance.
Combine technologies
A lot is possible here, but I'd really need to know more of your situation to assist in this direction. Often, I end up combining dynamic with generics, with cached reflection. When using information hiding (as is normal in OOP), you may end up with a fast, stable and still well-extensible solution.
Losing compile time type safety
Of the five questions, this is perhaps the most important one to worry about. It is very important to create your own exceptions that give clear information about reflection mistakes. That means: every call to a method, constructor or property based on an input string or otherwise unchecked information must be wrapped in a try/catch. Catch only specific exceptions (as always, I mean: never catch Exception itself).
Focus on TargetException (method does not exist), TargetInvocationException (method exists, but rose an exc. when invoked), TargetParameterCountException, MethodAccessException (not the right privileges, happens a lot in ASP.NET), InvalidOperationException (happens with generic types). You don't always need to try to catch all of them, it depends on the expected input and expected target objects.
To sum it up
Get rid of your Activator.CreateInstance and use MethodInfo to find the factory-create method, and use Delegate.CreateDelegate to create and cache the delegate. Simply store it in a static Dictionary where the key is equal to the class-string in your example code. Below is a quick but not-so-dirty way of doing this safely and without losing too much type safety.
Sample code
public class TestDynamicFactory
{
// static storage
private static Dictionary<string, Func<ICalculate>> InstanceCreateCache = new Dictionary<string, Func<ICalculate>>();
// how to invoke it
static int Main()
{
// invoke it, this is lightning fast and the first-time cache will be arranged
// also, no need to give the full method anymore, just the classname, as we
// use an interface for the rest. Almost full type safety!
ICalculate instanceOfCalculator = this.CreateCachableICalculate("RandomNumber");
int result = instanceOfCalculator.ExecuteCalculation();
}
// searches for the class, initiates it (calls factory method) and returns the instance
// TODO: add a lot of error handling!
ICalculate CreateCachableICalculate(string className)
{
if(!InstanceCreateCache.ContainsKey(className))
{
// get the type (several ways exist, this is an eays one)
Type type = TypeDelegator.GetType("TestDynamicFactory." + className);
// NOTE: this can be tempting, but do NOT use the following, because you cannot
// create a delegate from a ctor and will loose many performance benefits
//ConstructorInfo constructorInfo = type.GetConstructor(Type.EmptyTypes);
// works with public instance/static methods
MethodInfo mi = type.GetMethod("Create");
// the "magic", turn it into a delegate
var createInstanceDelegate = (Func<ICalculate>) Delegate.CreateDelegate(typeof (Func<ICalculate>), mi);
// store for future reference
InstanceCreateCache.Add(className, createInstanceDelegate);
}
return InstanceCreateCache[className].Invoke();
}
}
// example of your ICalculate interface
public interface ICalculate
{
void Initialize();
int ExecuteCalculation();
}
// example of an ICalculate class
public class RandomNumber : ICalculate
{
private static Random _random;
public static RandomNumber Create()
{
var random = new RandomNumber();
random.Initialize();
return random;
}
public void Initialize()
{
_random = new Random(DateTime.Now.Millisecond);
}
public int ExecuteCalculation()
{
return _random.Next();
}
}
I suggest you give your factory implementation a method RegisterImplementation. So every new class is just a call to that method and you are not changing your factories code.
UPDATE:
What I mean is something like this:
Create an interface that defines a calculation. According to your code, you already did this. For the sake of being complete, I am going to use the following interface in the rest of my answer:
public interface ICalculation
{
void Initialize(string originalData);
void DoWork();
}
Your factory will look something like this:
public class CalculationFactory
{
private readonly Dictionary<string, Func<string, ICalculation>> _calculations =
new Dictionary<string, Func<string, ICalculation>>();
public void RegisterCalculation<T>(string method)
where T : ICalculation, new()
{
_calculations.Add(method, originalData =>
{
var calculation = new T();
calculation.Initialize(originalData);
return calculation;
});
}
public ICalculation CreateInstance(string method, string originalData)
{
return _calculations[method](originalData);
}
}
This simple factory class is lacking error checking for the reason of simplicity.
UPDATE 2:
You would initialize it like this somewhere in your applications initialization routine:
CalculationFactory _factory = new CalculationFactory();
public void RegisterCalculations()
{
_factory.RegisterCalculation<Pivot>("Pivot");
_factory.RegisterCalculation<GroupBy>("GroupBy");
_factory.RegisterCalculation<StandardDeviation>("Standard deviation");
_factory.RegisterCalculation<PhosphoPRASPercentage>("% phospho PRAS Protein");
_factory.RegisterCalculation<AveragePPPperTreatment>("AveragePPPperTreatment");
_factory.RegisterCalculation<AvgPPPNControl>("AvgPPPNControl");
_factory.RegisterCalculation<PercentageInhibition>("PercentageInhibition");
}
Just as an example how to add initialization in the constructor:
Something similar to: Activator.CreateInstance(Type.GetType("ConsoleApplication1.Operation1"), initializationData);
but written with Linq Expression, part of code is taken here:
public class Operation1
{
public Operation1(object data)
{
}
}
public class Operation2
{
public Operation2(object data)
{
}
}
public class ActivatorsStorage
{
public delegate object ObjectActivator(params object[] args);
private readonly Dictionary<string, ObjectActivator> activators = new Dictionary<string,ObjectActivator>();
private ObjectActivator CreateActivator(ConstructorInfo ctor)
{
Type type = ctor.DeclaringType;
ParameterInfo[] paramsInfo = ctor.GetParameters();
ParameterExpression param = Expression.Parameter(typeof(object[]), "args");
Expression[] argsExp = new Expression[paramsInfo.Length];
for (int i = 0; i < paramsInfo.Length; i++)
{
Expression index = Expression.Constant(i);
Type paramType = paramsInfo[i].ParameterType;
Expression paramAccessorExp = Expression.ArrayIndex(param, index);
Expression paramCastExp = Expression.Convert(paramAccessorExp, paramType);
argsExp[i] = paramCastExp;
}
NewExpression newExp = Expression.New(ctor, argsExp);
LambdaExpression lambda = Expression.Lambda(typeof(ObjectActivator), newExp, param);
return (ObjectActivator)lambda.Compile();
}
private ObjectActivator CreateActivator(string className)
{
Type type = Type.GetType(className);
if (type == null)
throw new ArgumentException("Incorrect class name", "className");
// Get contructor with one parameter
ConstructorInfo ctor = type.GetConstructors()
.SingleOrDefault(w => w.GetParameters().Length == 1
&& w.GetParameters()[0].ParameterType == typeof(object));
if (ctor == null)
throw new Exception("There is no any constructor with 1 object parameter.");
return CreateActivator(ctor);
}
public ObjectActivator GetActivator(string className)
{
ObjectActivator activator;
if (activators.TryGetValue(className, out activator))
{
return activator;
}
activator = CreateActivator(className);
activators[className] = activator;
return activator;
}
}
The usage is following:
ActivatorsStorage ast = new ActivatorsStorage();
var a = ast.GetActivator("ConsoleApplication1.Operation1")(initializationData);
var b = ast.GetActivator("ConsoleApplication1.Operation2")(initializationData);
The same can be implemented with DynamicMethods.
Also, the classes are not required to be inherited from the same interface or base class.
Thanks, Vitaliy
One strategy that I use in cases like this is to flag my various implementations with a special attribute to indicate its key, and scan the active assemblies for types with that key:
[AttributeUsage(AttributeTargets.Class)]
public class OperationAttribute : System.Attribute
{
public OperationAttribute(string opKey)
{
_opKey = opKey;
}
private string _opKey;
public string OpKey {get {return _opKey;}}
}
[Operation("Standard deviation")]
public class StandardDeviation : IOperation
{
public void Initialize(object originalData)
{
//...
}
}
public interface IOperation
{
void Initialize(object originalData);
}
public class OperationFactory
{
static OperationFactory()
{
_opTypesByKey =
(from a in AppDomain.CurrentDomain.GetAssemblies()
from t in a.GetTypes()
let att = t.GetCustomAttributes(typeof(OperationAttribute), false).FirstOrDefault()
where att != null
select new { ((OperationAttribute)att).OpKey, t})
.ToDictionary(e => e.OpKey, e => e.t);
}
private static IDictionary<string, Type> _opTypesByKey;
public IOperation GetOperation(string opKey, object originalData)
{
var op = (IOperation)Activator.CreateInstance(_opTypesByKey[opKey]);
op.Initialize(originalData);
return op;
}
}
That way, just by creating a new class with a new key string, you can automatically "plug in" to the factory, without having to modify the factory code at all.
You'll also notice that rather than depending on each implementation to provide a specific constructor, I've created an Initialize method on the interface I expect the classes to implement. As long as they implement the interface, I'll be able to send the "originalData" to them without any reflection weirdness.
I'd also suggest using a dependency injection framework like Ninject instead of using Activator.CreateInstance. That way, your operation implementations can use constructor injection for their various dependencies.
Essentially, it sounds like you want the factory pattern. In this situation, you define a mapping of input to output types and then instantiate the type at runtime like you are doing.
Example:
You have X number of classes, and they all share a common interface of IDoSomething.
public interface IDoSomething
{
void DoSomething();
}
public class Foo : IDoSomething
{
public void DoSomething()
{
// Does Something specific to Foo
}
}
public class Bar : IDoSomething
{
public void DoSomething()
{
// Does something specific to Bar
}
}
public class MyClassFactory
{
private static Dictionary<string, Type> _mapping = new Dictionary<string, Type>();
static MyClassFactory()
{
_mapping.Add("Foo", typeof(Foo));
_mapping.Add("Bar", typeof(Bar));
}
public static void AddMapping(string query, Type concreteType)
{
// Omitting key checking code, etc. Basically, you can register new types at runtime as well.
_mapping.Add(query, concreteType);
}
public IDoSomething GetMySomething(string desiredThing)
{
if(!_mapping.ContainsKey(desiredThing))
throw new ApplicationException("No mapping is defined for: " + desiredThing);
return Activator.CreateInstance(_mapping[desiredThing]) as IDoSomething;
}
}
There's no error checking here. Are you absolutely sure that _class will resolve to a valid class? Are you controlling all the possible values or does this string somehow get populated by an end-user?
Reflection is generally most costly than avoiding it. Performance issues are proportionate to the number of objects you plan to instantiate this way.
Before you run off and use a dependency injection framework read the criticisms of it. =)
I have an object, MySession, that has a hashtable for storing arbitrary properties with arbitrary types. The relevant part of the object definition is:
public class MySession
{
private Hashtable _sessionVars;
///
/// Set and retrieve session variables ala the traditional session managers.
/// So, SessionObject["var1"] can be used to set or retrieve a value for var1.
///
/// Name of the variable to access.
/// An object that was stored in the session under key.
public object this[string key] {
get {
if (_sessionVars.ContainsKey(key)) {
return this._sessionVars[key];
}
return null;
}
set {
if (this._sessionVars.ContainsKey(key)) {
this._sessionVars.Remove(key);
}
this._sessionVars[key] = value;
}
}
}
The annoying thing is that I have to properly cast the properties when I want to use them. For example:
MySession session = new MySession();
if ( (bool)session["valid"] == true ) { /* do something fun */ }
I would rather be able to do:
MySession session = new MySession();
if ( session["valid"] == true ) { /* do something fun */ }
Is it possible to do this in C#? If so, how?
Update: I do not want to use explicit methods for accessing the properties. The point is to be able to access them as simply as possible. Not like session.GetProperty(name, type) or something.
If you think carefully, you will realize that this is inherently impossible.
What if you write session[someTextbox.Text]?
What if you assign two different types to the same identifier?
Compiling such code would involve solving the halting problem to figure out what type each string would have.
Instead, you could make a strongly-typed wrapper class around HttpContext.Current.Session with properties that include casts in their getters.
If you are using .Net Framework 4.0 then you can do it by deriving your MySession class from DynamicObject and overriding the necessary methods.
Here is the code:
public class MySession : DynamicObject
{
//Why not use Dictionary class?
private Hashtable _sessionVars = new Hashtable();
public override bool TrySetMember(SetMemberBinder binder, object value)
{
this[binder.Name] = value;
return true;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = this[binder.Name];
return true;
}
//You can make it private so that users do not use strings directly.
public object this[string key]
{
get
{
if (_sessionVars.ContainsKey(key))
{
return this._sessionVars[key];
}
return null;
}
set
{
if (this._sessionVars.ContainsKey(key))
{
this._sessionVars.Remove(key);
}
this._sessionVars[key] = value;
}
}
}
And this how you use it:
dynamic ses = new MySession();
ses.number = 5;
ses.boolean = true;
Console.WriteLine(ses.number > 4);
if (ses.boolean)
{
Console.WriteLine(ses.number - 1);
}
Console.ReadKey();
No need for casting or using string to access the new fields! If you are using Resharper you will get intellisense for existing fields too. If you need more functionality you can override other members too.
I personally end up having to handle the scenario where the session variable hasn't been set yet. Therefore, I end up with a method that looks like this:
public class MySession
{
...
public T GetValue<T>(string key, T defaultValue)
{
return _sessionVars.ContainsKey(key) ? this._sessionVars[key] as T : defaultValue;
}
}
Then T can be inferred. It can then be called like this (no casting required):
if (mySession.GetValue("valid", false))
{
// fun stuff here
}
I'm not really sure is "as T" works. If not, you can cast it to (T) done that before. "as T" would be nice if you've got inherited classes and such.
I typically derive off a class like mySession and call base.GetValue() in property getters I expose off the derived class.
If you're passing string (or any sort of object) keys, then it's impossible to do; the indexer method can only return one specific type, so you couldn't possible have it return a string or a double, for instance.
There are a couple of options: one, if this is a limited-scope class that doesn't need the flexibility of arbitrary keys, then you can just add explicit properties--maybe just for commonly used properties if you want to still be able to fall back on the object-returning indexer.
Or, you could add a generic Get method, like so:
public T GetValue<T>(object key) {
if(_hashSet[key] is T) {
return (T)_hashSet[key];
}
throw new InvalidCastException();
}
That doesn't get you much, though, since you'll still have to specify the type name, you're just moving it from the cast to the generic parameter.
EDIT: Of course, how you want to handle invalid casts is up to you, but throwing the exception mimics the behavior of the direct cast. As someone mentioned in another answer, if you also specify a parameter of type T in the signature, then it will get the correct type from that parameter.
Easy and best way to add session
public static void Add<T>(string key, T value)
{
var current = HttpContext.Current;
if (current == null) return;
current.Session.Add(key, value);
}
Example
public Model User
{
private string searchText
{
get { return SessionHelper.Get<string>("searchText"); }
set { SessionHelper.Add("searchText", value); }
}
}
How can I select the good method (I have in the example below show 2 differents way that doesn't work). I was using instead of a variable of type Object with a IF and IS to do the job but I am trying to avoid using Object and boxing/unboxing. So I thought that Generic could do the job but I am stuck here.
Here is a small snippet of code that illustrate my question:
class Program
{
static void Main(string[] args)
{
Parser p = new Parser();
ObjectType1 o1 = new ObjectType1();
p.execute(o1);
Console.Read();
}
}
class Parser
{
public T execute<T>(T obj)
{
/*
if (obj is ObjectType1)
this.action((ObjectType1)obj);
else if (obj is ObjectType2)
this.action((ObjectType2)obj);
*/
this.action(obj);
return obj;
}
private void action(ObjectType1 objectType1)
{
Console.WriteLine("1");
}
private void action(ObjectType2 objectType2)
{
Console.WriteLine("2");
}
}
class ObjectType1
{
}
class ObjectType2
{
}
Update
I do not want interface and class. Sorry. I knew that it's not the goal of the question.
Casting with (ObjectType)obj doesn't work but if you do :
if (obj is ObjectType1)
this.action(obj as ObjectType1);
else if (obj is ObjectType2)
this.action(obj as ObjectType1);
it works... why?
And... I cannot overload for all type the execute method because this method is from an Interface. This is why all need to be called from this method.
No, you can't do this. Generics don't work like C++ templates - the generic method is compiled just once. The only information that the compiler can use for overload resolution is the information it knows about within the generic method, regardless of what code uses it.
As an example to show this, here's a bit of code which may not work how you expect it to:
using System;
class Test
{
static void Main()
{
string x = "hello";
string y = string.Copy(x);
Console.WriteLine(x==y); // Overload used
Compare(x, y);
}
static void Compare<T>(T x, T y) where T : class
{
Console.WriteLine(x == y); // Reference comparison
}
}
It's hard to say the best way to proceed without knowing more about what you want to do.
Have you considered interfaces?
interface IAction
{
void action();
}
class ObjectType1 : IAction
{
void action() {
Console.WriteLine("1");
}
}
class ObjectType2 : IAction
{
void action() {
Console.WriteLine("2");
}
}
class Parser
{
public IAction execute(IAction obj)
{
obj.action();
return obj;
}
}
Edited by OP:
This solution would require to change all Business Logic Object to have this interface. This is really not a thing to do (in my situation). And, in other situation, I always prefer to have clean BusinessObject that doesn't have Interface not related with Business stuff. In my question, I want a solution that is more related with Generic/Object/Delegate method to achieve it. Thx you. This answer won't be accepted.
The class Parser has a lot of private method that are called by the execute method depending of the object type. It needs to redirect to the good method.
The compiler will do this work for you. Just use overloads.
class Parser
{
public ObjectType1 action(ObjectType1 objectType1)
{
Console.WriteLine("1");
return objectType1;
}
public ObjectType2 action(ObjectType2 objectType2)
{
Console.WriteLine("2");
return objectType2;
}
}
class ObjectType1 { }
struct ObjectType2 { }
Then, called with:
Parser p = new Parser();
p.action(new ObjectType1());
p.action(new ObjectType2());
There's no boxing/unboxing, and the appropriate method gets called.
I haven't tried it, but can you do this?
public T execute<T>(T obj)
{
this.action((T)obj);
return obj;
}
(according to comments, doesn't work)
or
public T execute<T>(T obj)
{
this.action(obj as T);
return obj;
}
(according to comments, works)
I know you're concerned about boxing/unboxing, so there could be ValueTypes involved here.
public T execute<T>(T obj)
{
this.action(obj);
return obj;
}
Supposing that action is modifying obj, and also supposing that modification is important to the caller (which is why you're returning the value back to the caller). This code has a nasty pass-by-value defect.
Consider this code:
public int execute(int obj)
{
this.action(obj);
return obj;
}
public void action(int obj)
{
obj = obj + 1;
}
Called in this way.
int x = p.execute(1);
x is 1, not 2.
Generics happens in compile time. It is best used when you want the same code to apply to different types. It is not dynamic, so it won't help you switch between methods depending on input types.
Overloading resolving as in David B's reply works, but also happens during compile time.
The code in your update does the same thing. It casts (after careful checking of types) and then uses overloading to resolve the method.
I feel that you want to switch methods based on runtime input.
You could get a more dynamic behaviour if you used Reflection.
public object execute(object obj)
{
MethodInfo m = typeof(Parser).GetMethod(
"action",
BindingFlags.Instance | BindingFlags.NonPublic,
null,
new Type[] { obj.GetType() },
null);
m.Invoke(this, new object[] { obj });
return obj;
}
It is perhaps a little fragile, but it works in the example.
IIRC you can use the "where" clause to allow this
public T execute<T>(T obj) where : /* somthing */
{
}
I always have to Google that one my self so I'll leave it at that.
edit: reading some comments. I would not advise calling type specific code. Rather put that code in a virtual function and call that. The call signature might get long, but that's what auto complete is for.
Koodos to joshua.ewer for finding the man page
My question concerns c# and how to access Static members ... Well I don't really know how to explain it (which kind of is bad for a question isn't it?) I will just give you some sample code:
Class test<T>{
int method1(Obj Parameter1){
//in here I want to do something which I would explain as
T.TryParse(Parameter1);
//my problem is that it does not work ... I get an error.
//just to explain: if I declare test<int> (with type Integer)
//I want my sample code to call int.TryParse(). If it were String
//it should have been String.TryParse()
}
}
So thank you guys for your answers (By the way the question is: how would I solve this problem without getting an error). This probably quite an easy question for you!
Edit: Thank you all for your answers!
Though I think the try - catch phrase is the most elegant, I know from my experience with vb that it can really be a bummer. I used it once and it took about 30 minutes to run a program, which later on only took 2 minutes to compute just because I avoided try - catch.
This is why I chose the switch statement as the best answer. It makes the code more complicated but on the other hand I imagine it to be relatively fast and relatively easy to read. (Though I still think there should be a more elegant way ... maybe in the next language I learn)
Though if you have some other suggestion I am still waiting (and willing to participate)
The problem is that TryParse isn't defined on an interface or base class anywhere, so you can't make an assumption that the type passed into your class will have that function. Unless you can contrain T in some way, you'll run into this a lot.
Constraints on Type Parameters
Short answer, you can't.
Long answer, you can cheat:
public class Example
{
internal static class Support
{
private delegate bool GenericParser<T>(string s, out T o);
private static Dictionary<Type, object> parsers =
MakeStandardParsers();
private static Dictionary<Type, object> MakeStandardParsers()
{
Dictionary<Type, object> d = new Dictionary<Type, object>();
// You need to add an entry for every type you want to cope with.
d[typeof(int)] = new GenericParser<int>(int.TryParse);
d[typeof(long)] = new GenericParser<long>(long.TryParse);
d[typeof(float)] = new GenericParser<float>(float.TryParse);
return d;
}
public static bool TryParse<T>(string s, out T result)
{
return ((GenericParser<T>)parsers[typeof(T)])(s, out result);
}
}
public class Test<T>
{
public static T method1(string s)
{
T value;
bool success = Support.TryParse(s, out value);
return value;
}
}
public static void Main()
{
Console.WriteLine(Test<int>.method1("23"));
Console.WriteLine(Test<float>.method1("23.4"));
Console.WriteLine(Test<long>.method1("99999999999999"));
Console.ReadLine();
}
}
I made a static dictionary holding a delegate for the TryParse method of every type I might want to use. I then wrote a generic method to look up the dictionary and pass on the call to the appropriate delegate. Since every delegate has a different type, I just store them as object references and cast them back to the appropriate generic type when I retrieve them. Note that for the sake of a simple example I have omitted error checking, such as to check whether we have an entry in the dictionary for the given type.
To access a member of a specific class or interface you need to use the Where keyword and specify the interface or base class that has the method.
In the above instance TryParse does not come from an interface or base class, so what you are trying to do above is not possible. Best just use Convert.ChangeType and a try/catch statement.
class test<T>
{
T Method(object P)
{
try {
return (T)Convert.ChangeType(P, typeof(T));
} catch(Exception e) {
return null;
}
}
}
One more way to do it, this time some reflection in the mix:
static class Parser
{
public static bool TryParse<TType>( string str, out TType x )
{
// Get the type on that TryParse shall be called
Type objType = typeof( TType );
// Enumerate the methods of TType
foreach( MethodInfo mi in objType.GetMethods() )
{
if( mi.Name == "TryParse" )
{
// We found a TryParse method, check for the 2-parameter-signature
ParameterInfo[] pi = mi.GetParameters();
if( pi.Length == 2 ) // Find TryParse( String, TType )
{
// Build a parameter list for the call
object[] paramList = new object[2] { str, default( TType ) };
// Invoke the static method
object ret = objType.InvokeMember( "TryParse", BindingFlags.InvokeMethod, null, null, paramList );
// Get the output value from the parameter list
x = (TType)paramList[1];
return (bool)ret;
}
}
}
// Maybe we should throw an exception here, because we were unable to find the TryParse
// method; this is not just a unable-to-parse error.
x = default( TType );
return false;
}
}
The next step would be trying to implement
public static TRet CallStaticMethod<TRet>( object obj, string methodName, params object[] args );
With full parameter type matching etc.
This isn't really a solution, but in certain scenarios it could be a good alternative: We can pass an additional delegate to the generic method.
To clarify what I mean, let's use an example. Let's say we have some generic factory method, that should create an instance of T, and we want it to then call another method, for notification or additional initialization.
Consider the following simple class:
public class Example
{
// ...
public static void PostInitCallback(Example example)
{
// Do something with the object...
}
}
And the following static method:
public static T CreateAndInit<T>() where T : new()
{
var t = new T();
// Some initialization code...
return t;
}
So right now we would have to do:
var example = CreateAndInit<Example>();
Example.PostInitCallback(example);
However, we could change our method to take an additional delegate:
public delegate void PostInitCallback<T>(T t);
public static T CreateAndInit<T>(PostInitCallback<T> callback) where T : new()
{
var t = new T();
// Some initialization code...
callback(t);
return t;
}
And now we can change the call to:
var example = CreateAndInit<Example>(Example.PostInitCallback);
Obviously this is only useful in very specific scenarios. But this is the cleanest solution in the sense that we get compile time safety, there is no "hacking" involved, and the code is dead simple.
Do you mean to do something like this:
Class test<T>
{
T method1(object Parameter1){
if( Parameter1 is T )
{
T value = (T) Parameter1;
//do something with value
return value;
}
else
{
//Parameter1 is not a T
return default(T); //or throw exception
}
}
}
Unfortunately you can't check for the TryParse pattern as it is static - which unfortunately means that it isn't particularly well suited to generics.
The only way to do exactly what you're looking for would be to use reflection to check if the method exists for T.
Another option is to ensure that the object you send in is a convertible object by restraining the type to IConvertible (all primitive types implement IConvertible). This would allow you to convert your parameter to the given type very flexibly.
Class test<T>
{
int method1(IConvertible Parameter1){
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
}
}
You could also do a variation on this by using an 'object' type instead like you had originally.
Class test<T>
{
int method1(object Parameter1){
if(Parameter1 is IConvertible) {
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
} else {
// Do something else
}
}
}
Ok guys: Thanks for all the fish. Now with your answers and my research (especially the article on limiting generic types to primitives) I will present you my solution.
Class a<T>{
private void checkWetherTypeIsOK()
{
if (T is int || T is float //|| ... any other types you want to be allowed){
return true;
}
else {
throw new exception();
}
}
public static a(){
ccheckWetherTypeIsOK();
}
}
You probably cant do it.
First of all if it should be possible you would need a tighter bound on T so the typechecker could be sure that all possible substitutions for T actually had a static method called TryParse.
You may want to read my previous post on limiting generic types to primitives. This may give you some pointers in limiting the type that can be passed to the generic (since TypeParse is obviously only available to a set number of primitives ( string.TryParse obviously being the exception, which doesn't make sense).
Once you have more of a handle on the type, you can then work on trying to parse it. You may need a bit of an ugly switch in there (to call the correct TryParse ) but I think you can achieve the desired functionality.
If you need me to explain any of the above further, then please ask :)
Best code: restrict T to ValueType this way:
class test1<T> where T: struct
A "struct" here means a value type.
String is a class, not a value type.
int, float, Enums are all value types.
btw the compiler does not accept to call static methods or access static members on 'type parameters' like in the following example which will not compile :(
class MyStatic { public static int MyValue=0; }
class Test<T> where T: MyStatic
{
public void TheTest() { T.MyValue++; }
}
=> Error 1 'T' is a 'type parameter', which is not valid in the given context
SL.
That is not how statics work. You have to think of statics as sort of in a Global class even if they are are spread across a whole bunch of types. My recommendation is to make it a property inside the T instance that can access the necessary static method.
Also T is an actual instance of something, and just like any other instance you are not able to access the statics for that type, through the instantiated value. Here is an example of what to do:
class a {
static StaticMethod1 ()
virtual Method1 ()
}
class b : a {
override Method1 () return StaticMethod1()
}
class c : a {
override Method1 () return "XYZ"
}
class generic<T>
where T : a {
void DoSomething () T.Method1()
}