So lets say I have two classes:
public class Account
{
public string Name{get;set;}
}
public class Account2
{
public string Name2{get;set;}
}
I want to write a generic method that will take in either one of these accounts and perform the exact same operation on both Name and Name2. So something like this.
public static void ProcessAccountNames<T>(List<T> accounts, string varName) where T: class
{
var name = account.GetType().GetProperty(varName).GetValue(account);
...
...
}
Then I could call
ProcessAccountNames<Account>(myAccountList, "Name");
ProcessAccountNames<Account2>(myAccount2List, "Name2");
I was wondering if there was any way In the method signature for me to specify that type T must contain an attribute named varName. Thanks!
Like Johnathan said, use an interface:
public interface INameable
{
string Name { get; }
}
Then for the second class where Name2 is the name of the property, add a Name property that returns Name2 as its get value.
Then on the generic signature, add
where T : class, INameable
EDIT
Johnathan's answer is probably what you want, though it doesn't strictly behave the way you asked for.
You could use expressions:
public static void ProcessAccountNames<T>(List<T> accounts, Expression<Func<T, string>> propSelector) where T: class
{
string propName = ((MemberExpression)propSelector.Body).Member.Name;
var name = account.GetType().GetProperty(propName).GetValue(account);
...
...
}
Then use like this:
ProcessAccountNames<Account>(myAccountList, x => x.Name);
ProcessAccountNames<Account2>(myAccount2List, x => x.Name2);
Or using type inference:
ProcessAccountNames(myAccountList, x => x.Name);
ProcessAccountNames(myAccount2List, x => x.Name2);
Although this could potentially be abused eg x => "some string"
resulting in an exception.
Another way would be to use nameof
, which would add some compiler safety:
ProcessAccountNames(myAccountList, nameof(Account.Name));
The only 100% type-safe way would be to add an interface and implement forwarding properties as per Chad's answer.
An alternative would to be to use delegates:
public static void ProcessAccountNames<T>(List<T> accounts, Func<T, string> getName) where T: class
{
var name = getName(account);
...
...
}
Which would still work like this:
ProcessAccountNames(myAccountList, x => x.Name);
ProcessAccountNames(myAccount2List, x => x.Name2);
Or you could provide a completely different function for retrieving a name, not restricted to property access:
ProcessAccountNames(myAccountList, x => "Some Name");
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.