I’m using an API that has an object that returns IEnumerable<T>, so something like Object.GetEnum<T>.
I have a method that within it will call GetEnum but I want to add to the method’s parameters the ability to pass the parameter type. So for example I want to do:
private void myMethod(apiClass??? apiclass)
{
IEnumerable< itemType > enumX = ObjectGetEnum< itemType >
}
private void Main()
{
myMethod(apiClass1);
myMethod(apiClass2);
}
So as above I don’t know what the parameter type should be in myMethod or how to write the code that gets the enumerator. I tried passing “apiClass”, the class which apiClass1 and apiClass2 inherit from. But then got stuck there on what to do…and I don’t think that really work anyways.
So I’m not sure if I just don’t know how in C# to do this, or if it is even possible, …. or perhaps I’m missing something in the API (or the API is missing something to facilitate this).
Thanks
FKC
Okay, I'm going to take a stab at this, although I'd like the question to be clarified. I suspect you just need to make the method generic:
private void MyMethod<TItem>() where TItem : ApiClass
{
IEnumerable<TItem> enumX = ObjectGetEnum<TItem>();
}
private static void Main()
{
MyMethod<ApiClass1>();
MyMethod<ApiClass2>();
}
Are you trying to access the type parameter of the closed constructed type inside a method? Maybe something like this will work:
using System;
class Foo<T> { }
class Program
{
static void Main()
{
myMethod(new Foo<String>());
}
private static void myMethod<T>(Foo<T> foo)
{
// use the T parameter in here
}
}
You need something like this:
private void myMethod<T>()
{
IEnumerable<T> enumX = ObjectGetEnum<T>();
}
Related
Alright, so I have a class. In that class I have the following property:
private Func<object, OutputEventArgs> _outputMethod = null;
public Func<object, OutputEventArgs> OutputMethod
{
get { return _outputMethod; }
set { _outputMethod = value; }
}
I want the class to be able to invoke this method which is going to allow it to send outputs (error messages and the like) to somewhere of my choosing.
That seems to work alright, but the issue comes when I want to assign that property.
I have another class called OutputHandler which looks like this:
public static class OutputHandler
{
public static void HandleOutput(OutputEventArgs e)
{
}
}
I'm aware I could just call that method directly from the class in question, but I want to enforce some kind of separation of concerns.
So my assignment is like this (c1 being an instance of the class with the Func in it):
c1.OutputMethod = ????
I've tried a few things, but none of them work. I've also looked up and down this site and come up with nothing so far.
Like others have mentioned, you can change your OutputMethod to an Action instead of a Func, or you can change:
public static void HandleOutput(OutputEventArgs e)
{
}
to
public static object HandleOutput(OutputEventArgs e)
{
}
I am currently trying to implement generic interface.
public interface IAssociatedTrie<T>
{
bool Contains(string key);
T GetValue(string key);
void Add(string key, T value);
}
I have a class which implements this interface
class Trie<T> : IAssociatedTrie<T>
{
//some work
public void Add(string key, T value)
{
//some work
}
...
}
And then I want to pass an instance of class with IAssociatedTrie interface to some method
static void Main(string[] args)
{
Trie<int> myTrie = new Trie<int>();
TestTrie(myTrie);
}
private static void TestTrie<T>(IAssociatedTrie<T> myTrie)
{
//some work
myTrie.Add("oa", 3); //error
//some work
}
But here I get CS1503 error "Can't convert int to T". I found that
myTrie.Add("oa", (T)(object)4);
fix the issue, but this looks very inelegant and I am preety sure I am doing something wrong. How should I modify method/class method for this to work without parsing to object->T?
Your method is generic. That means your code must work for any T.
Your code adding 3 works only for T = int. What if I call your method with T = Elephant? There is no way you can cast your 3 into an Elephant.
I don't know what you want to do exactly. Either using the constant 3 is wrong, or having a generic T is wrong. That is a thing only you can decide. But your compiler is correct in flagging this error. You cannot use the constant 3 as a value for a T.
when you say myTrie.Add("oa", 3); - I am not sure what is the point of having generic method in first place. However, looks you intended to use something like :
private static void TestTrie<T>(IAssociatedTrie<T> myTrie, T value)
{
myTrie.Add("oa", value);
}
I want to have something like:
AStaticClass.MakeCall(commonCmds => commonCmds.MethodOfAParticularClass)
So I want to have a lambda expression as an argument and have the delegate list the available set of methods of a particular class that I can access through intellisense with the lambda function. Then make a call to the passed in method.
i.e. commonCmds => commonCmds. {Lists all the methods of a particular class}
and then I want to have a method that makes that call.
I can't figure it out the proper method signature.
So far I have public void MakeCall(Action cmd) {cmd.invoke;} THis obviously does not work. I tried func, Expression and cannot figure it out.
Thank you so much for the help!
EDIT:
CmdsTwo and CmdsOne Can be static. However I would like to my classes up in this way, since it will make a lot my other work much easier.
public void Main(string []args) {
MyStaticClass.MakeCall(x => x.DoThis);
MyStaticClass.MakeCallTwo(x => x.DoThisTwo);
MyStaticClass.MakeCall(x => x.DoThisThree);
}
public static class MyStaticClass{
public static void MakeCall<???>( ??????)
public static void MakeCallTwo<???>( ??????)
}
public class Cmds{
public void DoThis();
public void DoThisThree();
}
public class CmdsTwo{
public void DoThisTwo();
}
}
The closest i can think of right now is this:
commonCmds => commonCmds.GetType().GetMethods()
This returns you an array of MethodInfo, which describe all methods of the type of commonCmds. You'd have to invoke one of those like this:
object result = someMethodInfo.Invoke(someObjectInstance, new object[] { someParameter });
You can check it
AStaticClass.MakeCall( () => commonCmds.MethodOfAParticularClass)
You need to use the generic version of Action With A Type.
public void MakeCall(Action<TYPE_HERE> cmd)
{
cmd.Invoke(...);
}
The type gets inferred and intellisense should kick in.
So I got it. Iused an extension method. Thank you.
public static class MyStaticClass{
public static void MakeCall(Action<Cmds> paramater){
Helper(new Cmds(), parameter);
}
private static void Helper(this Cmds, Action<Cmds> invokeThis) {...}
public static void MakeCallTwo<???>( ??????)
}
My guess until now was that a dynamic type just "switches off" type checking during compilation and does something similar to a type cast when a message is invoked on a dynamic instance. Obviously something else is going on.
The attached NUnit test case shows my problem: Using a dynamic type I can use a method only available in the concrete subclass, but I cannot do the same using a cast (results in InvalidCastException). I'd rather do the casting since this gives me full code completion in VS.
Can anyone explain what's happening and/or give me a hint how I could get code completion in my case without having to reimplement the WorkWithAndCreate-method in every concrete subclass?
cheers, Johannes
using System;
using NUnit.Framework;
namespace SlidesCode.TestDataBuilder
{
[TestFixture]
public class MyTest
{
[Test]
public void DynamicWorks()
{
string aString = CreateDynamic(obj => obj.OnlyInConcreteClass());
Assert.AreEqual("a string", aString);
}
private static string CreateDynamic(Action<dynamic> action)
{
return new MyConcreteClass().WorkWithAndCreate(action);
}
[Test]
public void CastingDoesNotWorkButThrowsInvalidCastException()
{
string aString = CreateWithCast(obj => obj.OnlyInConcreteClass());
Assert.AreEqual("a string", aString);
}
private static string CreateWithCast(Action<MyConcreteClass> action)
{
return new MyConcreteClass().WorkWithAndCreate((Action<MyGenericClass<string>>) action);
}
}
internal abstract class MyGenericClass<T>
{
public abstract T Create();
public T WorkWithAndCreate(Action<MyGenericClass<T>> action)
{
action(this);
return this.Create();
}
}
internal class MyConcreteClass : MyGenericClass<string>
{
public override string Create()
{
return "a string";
}
public void OnlyInConcreteClass()
{
}
}
}
Here's the formatted real world example from my comment:
Customer customer = ACustomer(cust =>
{
cust.With(new Id(54321));
cust.With(AnAddress(addr => addr.WithZipCode(22222)));
});
private static Address AnAddress(Action<AddressBuilder> buildingAction)
{
return new AddressBuilder().BuildFrom(buildingAction);
}
private static Customer ACustomer(Action<CustomerBuilder> buildingAction)
{
return new CustomerBuilder().BuildFrom(buildingAction);
}
Some details are missing from it but I hope it makes the purpose clear.
The reason dynamic works is that dynamic does not depend on compile time knowledge of the object types. MyGenericClass<string> does not have the method OnlyInConcreteClass(), but the instance you are passing of course does have the method and dynamic finds this.
By the way, you can make WorkWithAndCreate work like this:
public T WorkWithAndCreate<T1>(Action<T1> action)
where T1 : MyGenericClass<T>
{
action((T1)this);
return this.Create();
}
Then, the call will work too:
private static string CreateWithCast(Action<MyConcreteClass> action)
{
return new MyConcreteClass().WorkWithAndCreate(action);
}
You now don't have to cast it anymore.
And concerning your builder, would the following work?
private static TResult AnInstance<TBuilder, TResult>(Action<TBuilder> buildingAction)
where TBuilder : Builder<TResult>, new()
{
return new TBuilder().BuildFrom(buildingAction);
}
This is an example of how to use dynamic:
http://msdn.microsoft.com/en-us/library/dd264736.aspx
You said:
My guess until now was that a dynamic type just "switches off" type checking during compilation and does something similar to a type cast when a message is invoked on a dynamic instance
Actually, it uses reflections to look up the methods, properties, and fields you invoke by name, at runtime. No casting is done, unless you actually cast the object back to its underlying type.
As for your actual problem, can you give a more concrete example? There may be a better design, but you haven't told us what you're trying to do - just what you're currently doing.
Hazarding a guess, you may want to use a base interface, and make all your functions accept that base interface. Then put the methods you want to call on that interface, and implement them in your concrete types. Usually dynamic is used as a work around when you don't have a base type, or can't modify the base type to add virtual or abstract methods.
If you really want to get this working, as-is, you must write it with a generic type parameter, not a dynamic type parameter. See Pieter's solution for how to do this properly.
I had a thought on using the generic method in c# as like we do in c++.
Normally a method looks like this:
public static (void/int/string) methodname((datatype) partameter)
{
return ...;
}
I had a thought whether can we implement the generics to this method like this:
public static <T> methodname(<T> partameter)
{
return ...;
}
Using as a generic to define the datatype.
Can anyone pls suggest whether the above declaration is correct and can be used in c#?
Thanks in advance.
Not quite like that, no. It would be:
public static T MethodName<T>(T parameter)
{
...
}
The <T> after MethodName shows that it's introducing a type parameter.
EDIT: As per the comment, you can't use this for a void method - you can't use void as a type argument, basically.