How to write generic way method in C# - c#

I have individual methods such as:
public string Method1()
{
class1 c1= new class1 ();
var data = c1.GetMainData(Id);
var value= c1.GetValue(data,c1);
}
public string Method2()
{
class2 c2= new class2 ();
var data = c2.GetMainData(Id);
var value= c2.GetValue(data,c2);
}
public string Method3()
{
class3 c3 = new class3 ();
var data = c3.GetMainData(Id);
var value= c3.GetValue(data,c3);
}
From the above functions, classes class1, class2, and class3 are different but the method names GetMainData and GetValue are same in the class.
method names are same and passing class object to method and have different functionality and returning string.
Please help me to write a generic single method to handle?

Unlike C++, C# has only limited duck typing, and only for compiler internals (disposing) or extension methods. Neither of them apply here.
You have three options here. You either use a common polymorphic base type that allows you to call your methods:
interface I {
object GetMainData(int id);
object GetValue(int data);
}
class class1 : I {
// implement the interface
}
// same for class2 and class3
public string Method<T>() where T: I, new()
{
var c = new T();
var data = c.GetMainData(Id);
var value= c.GetValue(data);
// return something
}
You can also use reflection to call methods by name from unrelated objects.
And of course, you can use dynamic to create a compiler site to do the same for you.
Note that the last two are orders of magnitude slower than the first option, though dynamic's cost is mostly at the first call to build the site and compile the new generated code, subsequent calls are pretty fast.

have you tried writing a generic method?
interface IMyInterface
{
string GetMainData(string id);
string GetValue(string data);
}
string getValue<T>() where T:IMyInterface,new()
{
var c = new T();
var data = c.GetMainData(Id);
return c.GetValue(data);
}
the where clause indicates the minimum requirements of T, in this case any class passed as T must inherit from IMyInterface and have a empty constructor, because of this the compiler knows that T must have a new() and all methods and properties specified on the IMyInterface interface
additional note: if you are using an interface then the generics are probably not even required as you can call the instance functions with out knowing exactly what class they are
string getValue(IMyInterface c)
{
var data = c.GetMainData(Id);
return c.GetValue(data);
}
the generics is generally only required when you need the return or inputs to be the same type as T
the most common generic i write is a collection extentions
public static Add(this ICollection<T> col, IEnumerable<T> items)
{
foreach(var item in items)
col.Add(item)
}
here if the items are not the same type as the collection then the code doesn't work, however we actually don't care what type the items and collection are as long as they match

Related

deriving types from an array of individually typed classes

I'm trying to come up with the best way to pass multiple individually typed classes into a method. I won't know beforehand how many individually typed classes will be passed into the method so have started the code off like this...
An Interface
public interface ITypedClass {}
A Typed Class
public class TypedClass<T> : ITypedClass
{
public IEnumerable<T> Output() {}
}
A Method
public static void DoSomething(params ITypedClass[] typedClasses) {}
... and with these run something like the following, where the DoSomething method populates the typed classes with respective values based on the collective of what is passed into the DoSomething method.
var typedClassA = new TypedClass<TypeA>();
var typedClassB = new TypedClass<TypeB>();
...
var typedClassN = new TypedClass<TypeN>();
DoSomething(typedClassA, typedClassB, ... typedClassN etc
var valueA - typedClassA.Output();
var valueB - typedClassB.Output();
...
var valueN - typedClassN.Output();
Unfortunately inside the DoSomething method...
var typedClass = (TypedClass<T>)typedClasses.First();
... the individual values in the typedClasses parameter can't be converted back to TypedClass because the DoSomething method doesn't know what T is in each instance.
Can anyone think of a better way to do this?
The answer seems a little bit obvious with more thought. Had to sleep on it a few nights before the obviousness finally clicked. Don't have DoSomething process the typed input, have TypedClass do it for you and instead have DoSomething split up the work.
New Interface
public interface ITypedClass
{
void Input(object value);
}
New Typed Class
The Input method here handles the conversion from object value to List value
public class TypedClass<T> : ITypedClass
{
public List<T> value;
public void Input(object value) {...}
public IEnumerable<T> Output() => value;
}
New Method
DoSomething now divides up the work...
public static void DoSomething(params ITypedClass[] typedClasses)
{
foreach (var c in typedClasses)
{
c.Input(...);
}
}
Now when calling the following ...
var typedClassN = new TypedClass<TypeN>();
DoSomething(... typedClassN ... );
var valueN = typedClassN.Output();
valueN will have a value and DoSomething can handle a variable amount of typed classes

How can I add an extension method to many classes?

I have about 1000 classes in which i need to count the number of properties of. I have the following code:
public static int NumberOfProperties()
{
Type type = typeof(C507);
return type.GetProperties().Count();
}
I could copy and paste this in to each class changing the typeof parameter but this seems a bit tedious.
Is there anyway to make an extensions method to do this by just doing var nop = C507.NumberOfProperties();?
Just to add to the answers suggesting an extension for object for completeness: you can also consider implementing an extension only for Type:
public static int GetPropertyCount(this Type t)
{
return t.GetProperties().Length;
}
and use it like this:
typeof(C507).GetPropertyCount();
The advantage is that you can get the number of properties directly from the type and do not have to create an instance first.
So you can write an extension method that uses object or one that uses type.
public static class ObjectExtensions
{
public static int GetNumberOfProperties(this object value)
{
return value.GetType().GetProperties().Count();
}
public static int GetNumberOfProperties(this Type value)
{
return value.GetProperties().Count();
}
}
Usage:
new C507().GetNumberOfProperties();
typeof(C507).GetNumberOfProperties();
However, you explicitly state two things:
I could copy and paste this in to each class changing the typeof
I have about 1000 classes
You'll likely not want to instantiate a 1000 classes or copy and paste typeof() 1000 times
In this case, you will want to read them all from the Assembly.
So something like:
typeof(SomeClass).Assembly.GetTypes().Select(x => new
{
x.Name,
PropertyCount = x.GetType().GetProperties().Count()
});
Where SomeClass is a class (doesn't matter which) where all the classes reside.
I just simply select them out into an anonymous object which contains the Types name and property count.
This:
typeof(SomeClass).Assembly
Is just a convience way to get the assembly. There are other ways.
Assembly.GetAssembly(typeof(Program)).GetTypes()
Assembly.GetCallingAssembly().GetTypes()
Assembly.Load("Some Assemble Ref").GetTypes()
You can do allsorts with the types that you find. If you select out the Type itself, you can instantiate it later using Activator.CreateInstance (if it has parameterless constuctor). You can also auto fill the properties with reflection as well.
It is impossible to have a static extension method as you imagine it. That being said, it would be possible to create a generic method in a helper class as follows.
public static int NumberOfProperties<T>()
{
Type type = typeof(T);
return type.GetProperties().Count();
}
Given a type SomeType it could be called as int n = NumberOfProperties<SomeType>().
You could make an extension method on object like this:
public static int PropertyCount(this object thing)
{
return thing.GetType().GetProperties().Count();
}
And use it on any object you like:
var x = "some string";
var numProps = x.PropertyCount();
If you want to have an extension method on object:
public static ObjectExtensions
{
public static int NumberOfProperties(this object value)
{
if (null == value)
throw new ArgumentNullException("value"); // or return 0
// Length: no need in Linq here
return value.GetType().GetProperties().Length;
}
}
...
C507 myObj = new C507();
// How many properties does myObj instance have?
int propCount = myObj.NumberOfProperties();
If you want to have an extesnion method on Type:
public static TypeExtensions
{
public static int NumberOfProperties(this Type value)
{
if (null == value)
throw new ArgumentNullException("value"); // or return 0
// Length: no need in Linq here
return value.GetProperties().Length;
}
}
...
// How many properties does C507 type have?
int propCount = typeof(C507).NumberOfProperties();
There are a couple of ways to do this that are variations of the same thing.
You can pass the Type as an argument to a method:
public static class Helper {
public static int NumberOfProperties(Type type)
{
return type.GetProperties().Count();
}
}
Which you would call like this:
// Imagine you have a class called MyClass
var result = Helper.NumberOfProperties(typeof(MyClass));
You use use the generic system in C# to make the syntax a little cleaner. That would look like this:
public static class Helper {
// Notice the argument was removed and
// the use of the "generic" syntax <T>
public static int NumberOfProperties<T>()
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
And you would call it like this:
var result = Helper.NumberOfProperties<MyClass>();
You could also use "Extensions" which allow you to call it as if it was a method that belonged to your classes.
public static class Helper {
// notice the `this` keyword before the parameter
// this is what tells C# that this is an extension method
public static int NumberOfProperties<T>(this T #this)
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
This will allow you to call the method like this:
var instance = new MyClass();
var result = instance.NumberOfProperties();
In this example I used the generic syntax so that it applies to any type of object. If you wanted to limit it to only objects that inherit from a specific interface or base class you would just change it from using the generic syntax to using the base class/interface. Like this:
public static class Helper {
// notice the type got changed from a generic <T>
// to specifying the exact class you want to "extend"
public static int NumberOfProperties(this MyBaseClass #this)
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
As #rené-vogt mentioned you can also create the extension method so that it extends the type Type instead. See his answer in this thread: https://stackoverflow.com/a/38455233/984780
You can make a generic extension method which can apply to all types:
public static int PropertyCount<T>(this T obj)
{
return typeof(T).GetProperties().Length;
}
This will apply to all types including value types (I.E. structs) which applying to object will not. Thanks to piedar for pointing out my mistake here, applying to object does still add this extension method to value types.
If your classed can implement an interface, then you can extend that interface.
public interface IExtensible {
}
class C507 : IExtensible {
}
public static int NumberOfProperties(this IExtensible extensible)
{
Type type = extensible.GetType();
return type.GetProperties().Count();
}
That being said, having hundreds of (generated?) classes looks like a bad solution to begin with.

Get list of property names using interface method

I have two custom types Customer and Employee which implement the interface ITablefy. This interface has only one method, GetPropertyList which returns a list of strings of the property names of the object that implements it. I have a web service which looks like:
public string ReturnPropertyNames(ITablefy i)
{
List<string> propList = new List<string>();
TableFactory factory = new TableFactory();
ITablefy table = factory.CreateTable(i);
propList = table.GetPropertyList(table);
return propList[1];
}
so in this example the Factory creates a concrete type that implements ITablefy
I realized when I had a problem when both of my classes Customer and Employee implemented their GetPropertyList methods exactly the same:
//property list is a private member variable in each class
public List<string> GetPropertyList(ITablefy i)
{
TableFactory factory = new TableFactory();
ITablefy table = factory.CreateTable(i);
foreach (var propInfo in table.GetType().GetProperties())
{
propertyList.Add(propInfo.Name);
}
return propertyList;
}
Rather than copy and paste that code I'm looking for a better solution to what I have currently. If I only want certain types to use the GetPropertyList method how can I control that without having to copy and paste this same code? Harcoding the type to create in each class doesn't seem like a good solution to me. Employee and Customer don't logically make sense to use inheritance either. What's a proper solution for something like this?
factory:
public class TableFactory
{
public ITablefy CreateTable(ITablefy i)
{
if (i is Employee)
{
return new Employee();
}
else if (i is Customer)
{
return new Customer();
}
else
{
return null;
}
}
}
public static List<string> GetPropertyNames(this Object o)
{
List<string> names = new List<string>
foreach (PropertyInfo prop in o.GetType().GetProperties())
names.Add(prop.Name);
return names;
}
Now you can implement ITablefy in terms of any object.GetPropertyNames() using the extension method above.
There are a few questions that comes to my mind:
If It's so easy to do generically, why are you even using the interface?
Shouldn't you be checking properties for public accessors?
Shouldn't your interface be returning a more general type like IEnumerable<string> or ICollection<string>?
Wouldn't the interface be better designed to filter out property names that you don't want? That way you could assume all public properties are part of the set except those that aren't.
You make the interface be something like:
public interface IPropertyInfoFilterProvider {
public Func<PropertyInfo, bool> PropertyInfoSkipFilter { get; set; }
}
or
public interface IPropertyNameFilterProvider {
public Func<string, bool> PropertyNameSkipFilter { get; set; }
}
and then you can initialize the default to (prop) => false.
so now you can harvest the property names automagically and in one place and let implementations determine what gets taken and what doesn't and your harvesting code could use that filter in a linq where clause.
You could make it an extension method on ITablefy.
Or a static method on ITablefy

Casting a generic element type downwards

public class ConfigControlBase<T> : UserControl
where T : ProviderBase
{
public T Provider { get; set; }
public void Init(T provider)
{
this.Provider = provider;
}
}
public abstract class ProviderBase
{
public abstract ConfigControlBase<ProviderBase> GetControl();
}
public class ProviderXConfigControl : ConfigControlBase<ProviderX>
{
}
public class ProviderX : ProviderBase
{
public override ConfigControlBase<ProviderBase> GetControl()
{
var confControl = new ProviderXConfigControl() as ConfigControlBase<ProviderX>;
return confControl;
}
}
return confControl; throws an exception:
Cannot implicitly convert type ConfigControlBase<ProviderX> to ConfigControlBase<ProviderBase>
Let's change the name of your classes and properties, but keep the shape the same:
public class Cage<T> where T : Animal
{
public T Contents { get; set; }
}
public class Aquarium : Cage<Fish> { }
public abstract class Animal
{
public abstract Cage<Animal> GetCage();
}
public class Fish : Animal
{
public override Cage<Animal> GetCage()
{
return (Cage<Animal>)(new Aquarium());
}
}
Now is it clear why this is not legal? Suppose it were legal. Then you could do this:
Fish fish = new Fish();
Cage<Animal> cage = fish.GetCage();
cage.contents = new Tiger();
And now you have a tiger in your aquarium. And no one wants that.
The compiler (or runtime) has to prevent this type error somehow; it chooses to prevent it as soon as possible. The earliest it can do so is on the type test for the conversion from Aquarium to Cage<Animal>. The compiler knows that this can eventually lead to tigers in aquariums, so it does not allow the conversion at all. If you force the compiler to allow it through casts then it fails at runtime.
Generic types with assignable type arguments are not assignable themselves.
For instance, you cannot cast List<string> to List<object>, although string is an object.
It is not immediately obvious why such casting is not supported so let me give you an example:
var words = new List<string> { "Serve God", "love me", "mend" };
var objects = (List<object>) words; // C# compiler wouldn't allow this
objects.Add (new Car()); // we just added a Car to Shakespeare's work and the universe exploded
C# doesn't encourage universe explosion, however since C# 4.0 a light version of this idea is implemented. You see, in some cases such casting would actually be safe.
.NET 4.0 brings concepts of covariance and contravariance in generics only for interfaces and delegates, you may want to check this out.
Example (doesn't work prior to .NET 4.0):
void HandleCollection (IEnumerable<object> collection)
{
// ...
}
var words = new List<string> { "Serve God", "love me", "mend" };
// IEnumerable is defined as IEnumerable<out T> in .NET 4.0
// 'out' keyword guarantees that T is only used for return values
// and therefore client code can't explode the universe
var objects = (IEnumerable<object>) words;
HandleCollection (objects);
This is because ConfigControlBase<ProviderX> is not a ConfigControlBase<ProviderBase>
your
public override ConfigControlBase<ProviderBase> GetControl()
doesn't match
var confControl = new ProviderXConfigControl() as ConfigControlBase<ProviderX>;
This answer might not be useful in your scenario, as you should probably look for another solution, but during reflection I found the ability to cast to less generic types very useful, hence I wrote a solution for it. It only works for interfaces however, and you do have to guarantee you will only pass objects of the correct types to the interface.
I basically generate a proxy class at runtime which does all the required casts for you. It's usage looks as follows:
object validator; // An object known to implement IValidation<T>.
object toValidate; // The object which can be validated by using the validator.
// Assume validator is IValidation<string> and toValidate a string.
IValidation<object> validation
= Proxy.CreateGenericInterfaceWrapper<IValidation<object>>( validator );
validation.IsValid( toValidate ); // This works! No need to know about the type.
// The following will throw an InvalidCastException.
//validation.IsValid( 10 );
More information and source code can be found on my blog.

Adding generic object to generic list in C#

I have class where the relevant part looks like
class C {
void Method<T>(SomeClass<T> obj) {
list.Add(obj);
}
List<?> list = new List<?>();
}
How should I define the list so that the class compiles?
I want a list of type List<SomeClass<?>>, that is a list of objects of SomeClass where each object can have any type parameter. The Java ? construct allows this; what is the C# equivalent? If no such thing exists, is there a suitable workaround? (A List<object> would do but is terribly ugly.)
I don't think you can do this in C#... you would have to add the type parameter to the class:
class C<T> {
void Method(SomeClass<T> obj) {
list.Add(obj);
}
List<SomeClass<T>> list = new List<SomeClass<T>>();
}
The other option would be to use an interface:
class C {
void Method<T>(T obj)
where T : ISomeClass {
list.Add(obj);
}
List<ISomeClass> list = new List<ISomeClass>();
}
To do what you want, you have two options.
You can use List<object>, and handle objects. This will not be typesafe, and will have boxing/unboxing issues for value types, but it will work.
Your other option is to use a generic constraint to limit to a base class or interface, and use a List<Interface>.
Unfortunately, there is no direct equivalent in C# 3.0 as generics are invariant.
You'll be able to do something like this in a graceful manner using C# 4.0 safe co/contra-variance feature.
To workaround it, you could inherit SomeClass<T> from a nongeneric base and create a List<BaseClass> instead.
If each instance of the class should hold only one type, you could make the class itself generic and set the type parameter there.
I don't know anything about Java's ? construct, but I think the following most closely preserves your existing syntax while also matching your description.
class SomeClass<T>
{
}
class C
{
void Add<T>(SomeClass<T> item)
{
Type type = typeof(SomeClass<T>);
if (!list.ContainsKey(type))
list[type] = new List<SomeClass<T>>();
var l = (List<SomeClass<T>>)list[type];
l.Add(item);
}
public void Method<T>(SomeClass<T> obj)
{
Add(obj);
}
readonly Dictionary<Type, object> list = new Dictionary<Type, object>();
}
test it with the following:
class Program
{
static void Main(string[] args)
{
var c = new C();
var sc1 = new SomeClass<int>();
var sc2 = new SomeClass<String>();
c.Method(sc1);
c.Method(sc2);
c.Method(sc1);
c.Method(sc2);
}
}
Personally, I would do this where possible; move the generic parameter from the method, to the class.
class C<T> {
void Method(SomeClass<T> obj) {
list.Add(obj);
}
List<?> list = new List<?>();
}
If your generic list is a member, it stands to reason that the class should be constructed with this in mind. It is hard for us to suggest the best pattern without more usage context for the class.

Categories

Resources