Constructor Argument Enums and Magic Strings - c#

I am working on my c# .net application and use implement IoC/DI pattern using Ninject, Now Ninject has a class named ConstructorArgument which takes two arguments(argName,argValue).
So i need to pass static argName something like this
new ConstructorArgument("strVar","")
passing hardcoded string does not seems like a good option.
So i want to create something like dynamics enums using reflection for the constructor arguments, so i dont need to pass hardcoded strings.
Please guide me through this process or suggest me something else to achieve this.

like dynamics enums
There is no such construct readily available. If you really hate the strings, you could write some kind of expression-tree lambda (i.e. () => new Foo(strVal: "") or () => new Foo(""), however - that a: is a lot of work, and b: won't work well if there are other parameters being provided by the container.
To be honest, this is a bit of a non-issue, especially since named arguments mean that parameter names should be treated as a contract. IMO, just use the string. If it worries you, make sure you cover the scenario in a unit test, so that you find out early if it changes.

I agree with #Mark Gravell's stance, except that obfuscators can rename parameters for non-public ctors so the advice doesn't apply in that specific case, so in some cases, you need to whack on a [Obfuscation] on the parameter to preserve the name in some instances.
But I have built nonsense like this which would answer your question. Please don't use it as I regret writing it!
static class StaticReflection<TClass>
{
static string PublicConstructorParameterName<TParameter>()
{
return typeof( TClass ).GetConstructors( BindingFlags.Public | BindingFlags.Instance ).Single().GetParameters().Where( param => param.ParameterType == typeof( TParameter ) ).Single().Name;
}
internal static ConstructorArgument CreateConstructorArgument<TParameter>( TParameter value )
{
return new ConstructorArgument( PublicConstructorParameterName<TParameter>(), value );
}
internal static ConstructorArgument CreateConstructorArgument<TParameter>( Func<IContext, TParameter> argumentResolver )
{
return new ConstructorArgument( PublicConstructorParameterName<TParameter>(), context => (object)argumentResolver( context ) );
}
}
Which works like this:
public class StaticReflectionFacts
{
public class X2
{
}
public class X
{
public X( object param1, X2 param2 )
{
}
}
[Fact]
static void DeriveNinjectConstructorArgumentFromPublic()
{
var newArg = StaticReflection<X>.CreateConstructorArgument( new X2() );
Assert.Equal( "param2", newArg.Name );
}
}

I have imlemented this:
public string GiveConstuctorArgumentName(Type class, Type constructorArgument)
{
var cons = class.GetConstructors();
foreach (var constructorInfo in cons)
{
foreach (var consParameter in constructorInfo.GetParameters())
{
if (consParameter.ParameterType == constructorArgument)
{
return consParameter.Name;
}
}
}
throw new InstanceNotFoundException();
}
Its without LINQ, but its a good start point to understand how its work.

Related

Alternative to: Static class as Generic-Parameter

I do have a lot of static classes that represent different states in different modules. However they share common algorithms that extract its information.
public static class Constants
{
public static readonly int A = 0;
}
So for now I have for each class multiple static functions that does this. They only differ in the type of the static class that is processed (and its overall name).
public static SelectListItem getConstantsSelectListItem()
{ // pseudo example
return new SelectListItem { Text = "A" , Value = Constants.A };
}
To remove current and avoid future codebloat, I'd like to use reflection on the static classes. Here's my approach, that would do the job (if it was possible):
public static ReturnType getProperties< T >()
{ // basically same logic as getConstantsSelectListItem
var propertyList = typeof( T ) .GetFields( BindingFlags.Public | BindingFlags.Static ).ToList();
foreach( var item in propertyList )
{
var curConstant = (int)( item.GetValue( null ) );
// do some work here..
}
}
var constantsProperties = getProperties<Constants>();
The error is:
static types cannot be used as argument types
I have read, that for generics only instances (and therefore no static classes) can be used.
What would be a good way to make something similar work?
The question C# - static types cannot be used as type arguments explains very well that this behavior is intended.
It doesn't tell what you should do. In my opinion you could use a singleton pattern to keep one instance of that class. One benefit of this is that you can use inheritance too, so you don't need reflection to do the trick you do now, you can just rely on the base class' method signature.
You can just pass a Type object as an argument instead of using generics. Since you have to do typeof(T) .GetFields( anyway, it's not like you have any static type safety that you're losing.
The other suggestion I would strongly make is to use dictionaries mapping strings to integers to represent your collections of constants. Using reflection like this is just giving you pain for no good reason, enforces weird, almost ritualistic rules on developers ("this static class is magic, don't add any strings"), and has worse performance.

Delphi Class of in C#

I know this question has been asked before, but I have yet to see a short, clear answer, so I'm hoping they won't remove this question and I will now get a clear answer:
I am currently working in C# 5.0; .NET 4.5; VS 2012. I am mostly a Delphi guy although I've done lots with C#.
In Delphi I have written hundreds of class factories that use the following sort of design (MUCH SIMPLIFIED HERE):
unit uFactory;
interface
type
TClassofMyClass = class of TMyClass;
TFactoryDict = TDictionary<TMyEnum, TClassofMyClass>;
var fDict:TFactoryDict;
implementation
procedure initDict;
begin
fDict:=TFactoryDict.create;
fDict.add(myEnum1, TMyClass1);
fDict.add(myEnum2, TMyClass2);
fDict.add(myEnum3, TMyClass3);
end;
function Factory(const aEnum: TMyEnum): TMyClass;
var
ClassofMyClass: TClassofMyClass;
begin
if fDict.TryGetValue(aEnum, ClassofMyClass) then
result := ClassofMyClass.Create(aParam);
end;
end.
Now: HOW do I do something like this in C#?! Seems there is NO 'class of ' type in C#. Am I missing something? How can I implement this type of class factory simply and elegantly in C#? This design can be implemented in Python as well - why should C# be worse?!
You can use Type:
Dictionary<ClassEnum, Type> TypeDictionary = new Dictionary<ClassEnum, Type>();
public void InitDictionary()
{
TypeDictionary.Add(ClassEnum.FirstClass, typeof(FirstClass));
//etc...
}
public object Factory(ClassEnum type)
{
if (!TypeDictionary.ContainsKey(type))
return null;
var constructor = TypeDictionary[type].GetConstructor(....);
return constructor.Invoke(....);
}
But I think you should use a generic method:
public T Factory<T>(): where T is MyBaseClass
{
var type = typeof(T);
var constructor = type.GetConstructor(....);
return constructor.Invoke(....) as T;
}
Here is a variety for parameterized construction:
public T Factory<T>(params object[] args): where T is MyBaseClass
{
var argList = new List<object>(args);
var type = typeof(T);
var argtypes = argList.Select(o => o.GetType()).ToArray();
var constructor = type.GetConstructor(argtypes);
return constructor.Invoke(args) as T;
}
And of course; As with the first example, this will throw a nullpointerexception if it can't find a matching constructor...
class Potato
{
}
class Potato1 : Potato
{
public Potato1(object[] param) { }
}
class Potato2 : Potato
{
public Potato2(object[] param);
}
enum MyEnum
{
E1, E2
}
Dictionary<MyEnum, Func<object[], Potato>> dict = new Dictionary<MyEnum, Func<object[], Potato>>(){
{MyEnum.E1,(d)=>new Potato1(d)},
{MyEnum.E2,(d)=>new Potato2(d)}
};
Potato Factory(MyEnum e, object[] param)
{
return dict[e](param);
}
If i understood you correct you want to have a reference to a static class. This is not possible in c#.
just one example of factory method implementation:
http://www.codeproject.com/Tips/328826/implementing-Factory-Method-in-Csharp
The C# language does not support meta classes.
So you'll have to implement your factory in another way. One way is to use a switch statement on an enum:
switch (aEnum)
{
case myEnum1:
return new MyClass1();
case myEnum2:
return new MyClass2();
.....
}
Another commonly used option is to do it with reflection which would allow you to write code closer to what you are used to doing.
And yet another option is to replace your dictionary of classes with a dictionary of delegates that return a new instance of your object. With lambda syntax that option yields very clean code.
The disadvantage of reflection is that you give up compile time type safety. So whilst the reflection based approach is probably closest to the Delphi code in the question, it's not the route that I personally would choose.
Rather than trying to shoe horn your Delphi solution into a language that does not want that approach, I suggest you look for the most idiomatic C# solution. Start with a web search for class factory.

Function in C# to call a class/method as in php

I'm taking my first steps in c # & asp.net and I'm enjoying it much.
Now, I have a question...
Is there a function in C# to call a class/method as in php?
For example:
$class = array(
"foo", // class name
"bar" // method name
);
$params = array(
"one",
"two"
);
call_user_func_array($class, $params); //execute Foo->bar("one","two");
Nope, there is nothing built in to do exactly that. You could build a method that does something similar using reflection, but it seems like a solution looking for a problem.
void Main()
{
CallUserFuncArray("UserQuery+Foo", "Bar", "One", "Two");
}
// Define other methods and classes here
public class Foo
{
public static void Bar(string a, string b){}
}
public void CallUserFuncArray(string className, string methodName, params object[] args)
{
Type.GetType(className).GetMethod(methodName).Invoke(null, args);
}
As others have noted, there are multiple ways to simulate this, but no "baked-in" functionality in C#. The most flexible way is with reflection, but you can do it in a much simpler (and easier to deal with) way if you know the list of methods you'll be calling beforehand.
class Foo
{
public static string FooA(int p1, int p2)
{
return "FooA:" + p1 + p2;
}
public static string FooB(int p1, int p2) { return "FooB:" + p1 + p2; }
public static string FooC(int p1, int p2) { return "FooC:" + p1 + p2; }
}
class Bar
{
//You can use Func<int, int, object> instead of a delegate type,
//but this way is a little easier to read.
public delegate string Del(int p1, int p2);
public static string DoStuff()
{
var classes = new Dictionary<string, Dictionary<string, Del>>();
classes.Add("Foo", new Dictionary<string, Del>());
classes["Foo"].Add("FooA", Foo.FooA);
classes["Foo"].Add("FooB", Foo.FooB);
classes["Foo"].Add("FooC", Foo.FooC);
//...snip...
return classes["Foo"]["FooA"](5, 7);
}
}
Which, by the way, does work.
If you don't know which methods you want to make available this way, I suggest you reconsider whaever you're trying to do. The only reason I can think of for using strings to choose your execution path would be if you were planning to get those strings from the user. Not only is it a huge no-no to expose inner details of your application like this, but it comes dangerously close to eval-type functionality. There's a reason C# doesn't have an eval method, and it isn't because the designers forgot to put it in.
As #StriplingWarrior said, there's no built-in equivalent of call_user_func_array, but you can do something like it with Reflection.
The problem is that Reflection code can get very complicated very quickly, and can be brittle and error-prone if you're not VERY careful.
For example the following function does what you want:
public static void CallUserFuncArray(string[] func, params string[] args)
{
var type = Type.GetType(func[0]);
if (type == null)
{
throw new ArgumentException("The specified Class could not be found");
}
var method = type.GetMethod(func[1], BindingFlags.Static | BindingFlags.Public);
if (method== null)
{
throw new ArgumentException("The specified Method could not be found");
}
method.Invoke(null, args);
}
You call it like this:
var func = new [] { "Foo", "Bar" };
var args = new [] { "one", "two" };
CallUserFuncArray(func, args);
The problems though are many.
The code only works if Bar is a public static method.
There's a whole new layer of complexity if you need to call an instance method on an object.
The code will explode if the parameters in the args array aren't just right for the target method.
There's no support here for calling methods that expect anything other than string parameters. It's possible to query the type of the arguments expected by the method and convert the types before calling 'Invoke', but you're getting even more messy.
There are many more edge cases that blow out the complexity of this code even more if you need to cater for them.
To paraphrase Carl Franklin (of dotNetRocks fame):
I had a problem I needed to solve, so I used Reflection. Now I have two problems.
I you find yourself need to do this sort of thing thenyou probably need to rethink your overall design.

C# feature request: implement interfaces on anonymous types

I am wondering what it would take to make something like this work:
using System;
class Program
{
static void Main()
{
var f = new IFoo {
Foo = "foo",
Print = () => Console.WriteLine(Foo)
};
}
}
interface IFoo
{
String Foo { get; set; }
void Print();
}
The anonymous type created would look something like this:
internal sealed class <>f__AnonymousType0<<Foo>j__TPar> : IFoo
{
readonly <Foo>j__TPar <Foo>i__Field;
public <>f__AnonymousType0(<Foo>j__TPar Foo)
{
this.<Foo>i__Field = Foo;
}
public <Foo>j__TPar Foo
{
get { return this.<Foo>i__Field; }
}
public void Print()
{
Console.WriteLine(this.Foo);
}
}
Is there any reason that the compiler would be unable to do something like this? Even for non-void methods or methods that take parameters the compiler should be able to infer the types from the interface declaration.
Disclaimer: While I do realize that this is not currently possible and it would make more sense to simply create a concrete class in this instance I am more interested in the theoretical aspects of this.
There would be a few issues with overloaded members, indexers, and explicit interface implementations.
However, you could probably define the syntax in a way that allows you to resolve those problems.
Interestingly, you can get pretty close to what you want with C# 3.0 by writing a library. Basically, you could do this:
Create<IFoo>
(
new
{
Foo = "foo",
Print = (Action)(() => Console.WriteLine(Foo))
}
);
Which is pretty close to what you want. The primary differences are a call to "Create" instead of the "new" keyword and the fact that you need to specify a delegate type.
The declaration of "Create" would look like this:
T Create<T> (object o)
{
//...
}
It would then use Reflection.Emit to generate an interface implementation dynamically at runtime.
This syntax, however, does have problems with explicit interface implementations and overloaded members, that you couldn't resolve without changing the compiler.
An alternative would be to use a collection initializer rather than an anonymous type. That would look like this:
Create
{
new Members<IFoo>
{
{"Print", ((IFoo #this)=>Console.WriteLine(Foo))},
{"Foo", "foo"}
}
}
That would enable you to:
Handle explicit interface implementation by specifying something like "IEnumerable.Current" for the string parameter.
Define Members.Add so that you don't need to specify the delegate type in the initializer.
You would need to do a few things to implement this:
Writer a small parser for C# type names. This only requires ".", "[]", "<>",ID, and the primitive type names, so you could probably do that in a few hours
Implement a cache so that you only generate a single class for each unique interface
Implement the Reflection.Emit code gen. This would probably take about 2 days at the most.
It requires c# 4, but the opensource framework impromptu interface can fake this out of the box using DLR proxies internally. The performance is good although not as good as if the change you proposed existed.
using ImpromptuInterface.Dynamic;
...
var f = ImpromptuGet.Create<IFoo>(new{
Foo = "foo",
Print = ReturnVoid.Arguments(() => Console.WriteLine(Foo))
});
An anonymous type can't be made to do anything except to have read-only properties.
Quoting the C# Programming Guide (Anonymous Types):
"Anonymous types are class types that
consist of one or more public
read-only properties. No other kinds
of class members such as methods or
events are allowed. An anonymous type
cannot be cast to any interface or
type except for object."
As long as we're putting out an interface wish list, I'd really like to be able to tell the compiler that a class implements an interface outside the class definition- even in a separate assembly.
For example, let's say I'm working on a program to extract files from different archive formats. I want to be able to pull in existing implementations from different libraries — say, SharpZipLib and a commercial PGP implementation — and consume both libraries using the same code without creating new classes. Then I could use types from either source in generic constraints, for example.
Another use would be telling the compiler that System.Xml.Serialization.XmlSerializer implements the System.Runtime.Serialization.IFormatter interface (it already does, but the compiler doesn't know it).
This could be used to implement your request as well, just not automatically. You'd still have to explicitly tell the compiler about it. Not sure how the syntax would look, because you'd still have to manually map methods and properties somewhere, which means a lot of verbiage. Maybe something similar to extension methods.
You could have something like anonymous classes in Java:
using System;
class Program {
static void Main() {
var f = new IFoo() {
public String Foo { get { return "foo"; } }
public void Print() { Console.WriteLine(Foo); }
};
}
}
interface IFoo {
String Foo { get; set; }
void Print();
}
Wouldn't this be cool. Inline anonymous class:
List<Student>.Distinct(new IEqualityComparer<Student>()
{
public override bool Equals(Student x, Student y)
{
return x.Id == y.Id;
}
public override int GetHashCode(Student obj)
{
return obj.Id.GetHashCode();
}
})
I'm going to dump this here. I wrote it a while ago but IIRC it works OK.
First a helper function to take a MethodInfo and return a Type of a matching Func or Action. You need a branch for each number of parameters, unfortunately, and I apparently stopped at three.
static Type GenerateFuncOrAction(MethodInfo method)
{
var typeParams = method.GetParameters().Select(p => p.ParameterType).ToArray();
if (method.ReturnType == typeof(void))
{
if (typeParams.Length == 0)
{
return typeof(Action);
}
else if (typeParams.Length == 1)
{
return typeof(Action<>).MakeGenericType(typeParams);
}
else if (typeParams.Length == 2)
{
return typeof(Action<,>).MakeGenericType(typeParams);
}
else if (typeParams.Length == 3)
{
return typeof(Action<,,>).MakeGenericType(typeParams);
}
throw new ArgumentException("Only written up to 3 type parameters");
}
else
{
if (typeParams.Length == 0)
{
return typeof(Func<>).MakeGenericType(typeParams.Concat(new[] { method.ReturnType }).ToArray());
}
else if (typeParams.Length == 1)
{
return typeof(Func<,>).MakeGenericType(typeParams.Concat(new[] { method.ReturnType }).ToArray());
}
else if (typeParams.Length == 2)
{
return typeof(Func<,,>).MakeGenericType(typeParams.Concat(new[] { method.ReturnType }).ToArray());
}
else if (typeParams.Length == 3)
{
return typeof(Func<,,,>).MakeGenericType(typeParams.Concat(new[] { method.ReturnType }).ToArray());
}
throw new ArgumentException("Only written up to 3 type parameters");
}
}
And now the method that takes an interface as a generic parameter and returns a Type that implements the interface and has a constructor (needs to be called via Activator.CreateInstance) taking a Func or Action for each method/ getter/setter. You need to know the right order to put them in the constructor, though. Alternatively (commented-out code) it can generate a DLL which you can then reference and use the type directly.
static Type GenerateInterfaceImplementation<TInterface>()
{
var interfaceType = typeof(TInterface);
var funcTypes = interfaceType.GetMethods().Select(GenerateFuncOrAction).ToArray();
AssemblyName aName =
new AssemblyName("Dynamic" + interfaceType.Name + "WrapperAssembly");
var assBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
aName,
AssemblyBuilderAccess.Run/*AndSave*/); // to get a DLL
var modBuilder = assBuilder.DefineDynamicModule(aName.Name/*, aName.Name + ".dll"*/); // to get a DLL
TypeBuilder typeBuilder = modBuilder.DefineType(
"Dynamic" + interfaceType.Name + "Wrapper",
TypeAttributes.Public);
// Define a constructor taking the same parameters as this method.
var ctrBuilder = typeBuilder.DefineConstructor(
MethodAttributes.Public | MethodAttributes.HideBySig |
MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
CallingConventions.Standard,
funcTypes);
// Start building the constructor.
var ctrGenerator = ctrBuilder.GetILGenerator();
ctrGenerator.Emit(OpCodes.Ldarg_0);
ctrGenerator.Emit(
OpCodes.Call,
typeof(object).GetConstructor(Type.EmptyTypes));
// For each interface method, we add a field to hold the supplied
// delegate, code to store it in the constructor, and an
// implementation that calls the delegate.
byte methodIndex = 0;
foreach (var interfaceMethod in interfaceType.GetMethods())
{
ctrBuilder.DefineParameter(
methodIndex + 1,
ParameterAttributes.None,
"del_" + interfaceMethod.Name);
var delegateField = typeBuilder.DefineField(
"del_" + interfaceMethod.Name,
funcTypes[methodIndex],
FieldAttributes.Private);
ctrGenerator.Emit(OpCodes.Ldarg_0);
ctrGenerator.Emit(OpCodes.Ldarg_S, methodIndex + 1);
ctrGenerator.Emit(OpCodes.Stfld, delegateField);
var metBuilder = typeBuilder.DefineMethod(
interfaceMethod.Name,
MethodAttributes.Public | MethodAttributes.Virtual |
MethodAttributes.Final | MethodAttributes.HideBySig |
MethodAttributes.NewSlot,
interfaceMethod.ReturnType,
interfaceMethod.GetParameters()
.Select(p => p.ParameterType).ToArray());
var metGenerator = metBuilder.GetILGenerator();
metGenerator.Emit(OpCodes.Ldarg_0);
metGenerator.Emit(OpCodes.Ldfld, delegateField);
// Generate code to load each parameter.
byte paramIndex = 1;
foreach (var param in interfaceMethod.GetParameters())
{
metGenerator.Emit(OpCodes.Ldarg_S, paramIndex);
paramIndex++;
}
metGenerator.EmitCall(
OpCodes.Callvirt,
funcTypes[methodIndex].GetMethod("Invoke"),
null);
metGenerator.Emit(OpCodes.Ret);
methodIndex++;
}
ctrGenerator.Emit(OpCodes.Ret);
// Add interface implementation and finish creating.
typeBuilder.AddInterfaceImplementation(interfaceType);
var wrapperType = typeBuilder.CreateType();
//assBuilder.Save(aName.Name + ".dll"); // to get a DLL
return wrapperType;
}
You can use this as e.g.
public interface ITest
{
void M1();
string M2(int m2, string n2);
string prop { get; set; }
event test BoopBooped;
}
Type it = GenerateInterfaceImplementation<ITest>();
ITest instance = (ITest)Activator.CreateInstance(it,
new Action(() => {Console.WriteLine("M1 called"); return;}),
new Func<int, string, string>((i, s) => "M2 gives " + s + i.ToString()),
new Func<String>(() => "prop value"),
new Action<string>(s => {Console.WriteLine("prop set to " + s);}),
new Action<test>(eh => {Console.WriteLine(eh("handler added"));}),
new Action<test>(eh => {Console.WriteLine(eh("handler removed"));}));
// or with the generated DLL
ITest instance = new DynamicITestWrapper(
// parameters as before but you can see the signature
);
Interesting idea, I'd be a little concerned that even if it could be done it might get confusing. E.g. when defining a property with non-trivial setters and getters, or how to disambiguate Foo if the the declaring type also contained a property called Foo.
I wonder if this would be easier in a more dynamic language, or even with the dynamic type and DLR in C# 4.0?
Perhaps today in C# some of the intent could be achieved with lambdas:
void Main() {
var foo = new Foo();
foo.Bar = "bar";
foo.Print = () => Console.WriteLine(foo.Bar);
foo.Print();
}
class Foo : IFoo {
public String Bar { get; set; }
public Action Print {get;set;}
}
This wouldn't be possible currently.
What would be the difference between this and simply making IFoo a concrete class instead? Seems like that might be the better option.
What it would take? A new compiler and tons of checks to ensure they didn't break the other features. Personally, I think it'd just be easier to require developers to just create a concrete version of their class.
I have used in Java the Amonimous Class through the "new IFoo(){...}" sintax and it's practical and easy when you have to quick implement a simple interface.
As a sample it would be nice to implement IDisposable this way on a legacy object used just one time instead of deriving a new class to implement it.

Generics in c# & accessing the static members of T

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()
}

Categories