Getting a member via string in C#? - c#

My question stems from MVC's SelectList (and previous generations). Basically the class takes in an IEnumerable and uses the members you define as strings.
How does it interface with the object (casting, reflection?)
(probably redundant) How does it lookup the members as a string.
This is one facet of C# that I have been interested in but could never find examples of :(
EDIT:
I ended up using DataBinder.Eval() from System.Web.UI
It still has the overhead of reflection but makes things easier by allowing you to pass the object and a string containing the hierarchy of the member you want. Right now that doesn't really mean much, but this project was designed to take in Linq data, so not having to worry about it down the road makes my life a tad easier.
Thanks everyone for the help.

While I don't know about its implementation for sure, I'd expect it to use reflection.
Basically you call Type.GetProperty or Type.GetMethod to get the relevant member, then ask it for the value of that property for a specific instance (or call the method, etc). Alternatively there's Type.GetMembers, Type.GetMember etc.
If you want to be able to use "Person.Mother.Name" or similar "paths" you have to do that parsing yourself though, as far as I'm aware. (There may be bits of the framework to do it for you, but they're not in the reflection API.)
Here's a short but complete example:
using System;
using System.Reflection;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class Test
{
static void Main()
{
Person jon = new Person { Name = "Jon", Age = 33 };
ShowProperty(jon, "Name");
ShowProperty(jon, "Age");
}
static void ShowProperty(object target, string propertyName)
{
// We don't need no stinkin' error handling or validity
// checking (but you do if you want production code)
PropertyInfo property = target.GetType().GetProperty(propertyName);
object value = property.GetValue(target, null);
Console.WriteLine(value);
}
}

Yes, via reflection. Take a look at the Type class and associated methods. A good place to start might be here.
You can always look at MVC's source for examples too.

Related

C# Calling generic method for each field of class

I have a data class with several members
public interface IEquipmentHolder
{
ITypedServiceProvider<IGrabberChannel> VideoChannels { get; }
ITypedServiceProvider<IMicrophone> Microphones { get; }
ITypedServiceProvider<ISpeaker> Speakers { get; }
...
}
and a function
void visitChilds<T>(ITypedServiceProvider<T> childsList) where T : INamedComponent
{
...
}
In some place of my code, I want call the function for each field of the data class. So i do:
visitChilds(equipment.VideoChannels);
visitChilds(equipment.Microphones);
...
But, probably I am going to add some new fields in the data class and don't want to forget to fix these place after that.
My question: is it possible to to call generic function for each data member of the class using reflection? if it is not, can we put compile time check for new fields in the c# code?
How often are you going to add more fields and 'forget' to update calling code?
How fast are you going to find out that you've forgotten to add a call to visitChilds()?
How about IEquipmentHolder has only one property ITypedServiceProvider<INamedComponent> Items { get; }?
Reflection is slower than direct calls (maybe you should emit IL?) and the additional code may be just not worth the 'improvement', especially if it will be easy to spot that new set it not visited.
Also consider, that adding a new set of INamedComponents requires a breaking change to IEquipmentHolder interface and all implementations.
You could use the Expression framework to generate a lambda that will call visitChilds for each property on the interface.
You'd need to use reflection to generate the expression, but this would be a one off hit. After that you'd have a dynamically compiled lambda you could call that would be a lot quicker.
I've done something similiar before whereby I convert an instance of an object into a Dictionary<string,object> where each key is the name of a property and the value is the value of the property. We generated a lambda for each type we wanted to convert, and it worked really well.
If ITypedServiceProvider is covariant, i.e., declared like this,
ITypedServiceProvider<out T>
{
...
}
then you could have
IEquipmentHolder
{
IEnumerable<ITypedServiceProvider<INamedComponent>>
NamedComponents { get; }
}
then your could do
void VisitChildren(IEquipmentHolder equipment)
{
foreach(var provider in equipment.NamedComponents)
{
provider.SomeMemberOfITypedServiceProvider();
}
}

Object Oriented - Class Variables

I am pretty new to OOP and looking into things in a bit more depth, but I have a bit of confusion between these 3 methods in C# and which one is best and what the differences are between 2 of them.
Example 1
So lets start with this one, which (so I understand) is the wrong way to do it:
public class MyClass
{
public string myAttribute;
}
and in this way I can set the attribute directly using:
myObject.myAttribute = "something";
Example 2
The next way I have seen and that seems to be recomended is this:
public class MyClass
{
public string myAttribute { get; set;}
}
With getters and setters, this where I dont understand the difference between the first 2 as the variable can still be set directly on the object?
Example 3
The third way, and the way that I understand the theory behind, is creating a set function
public class MyClass
{
string myAttribute;
public void setAttribute(string newSetting)
{
myAttribute = newSetting;
//obviously you can apply some logic in here to remove unwanted characters or validate etc.
}
}
So, what are the differences between the three? I assume example 1 is a big no-no so which is best out of 2 and 3, and why use one over the other?
Thanks
The second
public class MyClass
{
public string MyAttribute { get; set;}
}
is basically shorthand for:
public class MyClass
{
private string myPrivateAttribute;
public string MyAttribute
{
get {return myPrivateAttribute;}
set {myPrivateAttribute = value;}
}
}
That is an auto-implemented property, which is exactly the same as any regular property, you just do not have to implement it, when the compiler can do that for you.
So, what is a property? It's nothing more than a couple of methods, coupled with a name. I could do:
public class MyClass
{
private string myPrivateAttribute;
public string GetMyAttribute()
{
return myPrivateAttribute;
}
public void SetMyAttribute(string value)
{
myPrivateAttribute = value;
}
}
but then instead of writing
myClass.MyAttribute = "something";
string variable = myClass.MyAttribute;
I would have to use the more verbose, but not necessarily clearer form:
myClass.SetMyAttribute("something");
string variable = myClass.GetMyAttribute();
Note that nothing constraints the contents of the get and set methods (accessors in C# terminology), they are methods, just like any other. You can add as much or as little logic as you need inside them. I.e. it is useful to make a prototype with auto-implemented properties, and later to add any necessary logic (e.g. log property access, or add lazy initalization) with an explicit implementation.
What your asking here has to do with encapsulation in OOP languages.
The difference between them is in the way you can access the propriety of an object after you created an object from your class.
In the fist example you can access it directly new MyClass().MyAttribute whether you get or set it's value.
In the second example you declare 2 basic functions for accessing it:
public string MyAttribute
{
get {return myPrivateAttribute;}
set {myPrivateAttribute = value;}
}
In the third example you declare your own method for setting the value. This is useful if you want to customize the setter. For example you don't want to set the value passed, but the value multiplied by 2 or something else...
I recommend some reading. You can find something here and here.
Property is a syntactic sugar over private attribute with get and set methods and it's realy helpful and fast to type;
You may treat automatic property with { get; set;} as a public attribute. It has no additional logic but you may add it later without uset ever notice it.
Just exchange
public string MyLine { get; set;}
to
string myLine;
public string MyLine
{
get { return myLine; }
set { myLine = value + Environment.NewLine; }
}
for example if you need so.
You can also easily create read only property as { get; private set }.
So use Properties instead of public attributes every time just because its easier and faster to write and it's provides better encapsulation because user should not be used get and set methods if you decide to use it in new version of yours programm.
One of the main principles of OOP is encapsulation, and this is essentially the difference between the first example and the other 2.
The first example you have a private field which is exposed directly from the object - this is bad because you are allowing mutation of internal data from outside the object and therefore have no control over it.
The other 2 examples are syntactically equivalent, the second being recommended simply because it's less code to write. However, more importantly they both restrict access & control mutation of the internal data so give you complete control over how the data should be managed - this is ecapsulation.

How to refactor when reflection is used to get methods by name?

Suppose I get a MethodInfo in the following way:
Assembly assembly = Assembly.Load(assemblyName);
Type type = assembly.GetType(nameSpaceName+"."+className);
MethodInfo mi = type.GetMethod("myMethod", bf); // bf are the binding flags.
But later I decide to change the case/name of myMethod.
Is there a way to either:
Refactor so that it changes the name in the string.
Change the reflection call so it gets the method without using the method's name as a string?
The reason for this is so I can test my code which requires the use of reflection, but I'd rather not require that nobody ever change the name of the methods in the code.
If you use Visual Studio to do the refactoring, there is an option to search literal strings and comments for the name and change those too. I highly recommend using the preview when using that option, though, to verify that you're only changing the parts you expect.
Of course, you could use a constant like internal const string methodName = "methodName"; so that you only have the literal string once. You could manually change the one string literal when you refactor the method name. You'd also be able to rename the methodName more easily.
You could use a custom attribute, and decorate your methods with this attribute. Then instead of getting the method by its name, you could get it by the ID defined in the attribute. That way the method name could change as often as it needs to...just a thought.
[AttributeUsage(AttributeTargets.Method)]
public class CustomMethodAttribute : Attribute
{
public string ID { get; set; }
}
Usage:
[CustomMethodAttribute(ID = "UniqueIDHere")]
public void Test()
{
}
Do you have a concrete reference to the type in question?
Even if you don't have it explicitly, you can make the method generic.
public void TestMethod<TargetType>(object o)
{
if (typeof(TargetType).IsAssignableFrom(o.GetType())) {
TargetType strongType = o as TargetType;
strongType.myMethod();
}
}
In fact, you could do this without reflection at all:
public void TestMethod<TargetType>(object o)
{
if (o is TargetType) {
TargetType strongType = o as TargetType;
strongType.myMethod();
}
}
For methods and properties try using expression trees.
You can get reflection-related information from them, saving compile-time checking and enabling automatic refactoring.
I believe you can get assembly-related information and namespace names as well.
Just write several helper functions which can retrieve such information from expression trees.
You can find several helper functions here
They allow write such code:
FirePropertyChanged(() => PropertyName);
which is the same as
FirePropertyChanged("PropertyName");

Is it bad practice to modify the variable within a method?

Which method style is better?
Is it generally bad practice to modify the variable within a method?
public class Person
{
public string Name { get; set;}
}
//Style 1
public void App()
{
Person p = new Person();
p.Name = GetName();
}
public string GetName()
{
return "daniel";
}
//Style 2
public void App()
{
Person p = new Person();
LoadName(p)
}
public void LoadName(Person p)
{
p.Name = "daniel";
}
There are times when both styles may make sense. For example, if you're simply setting the name, then perhaps you go with the first style. Don't pass an object into a method to mutate one thing, simply retrieve the one thing. This method is now more reusable as a side benefit. Think of it like the Law of Demeter or the principle of least knowledge.
In other cases, maybe you need to do a wholesale update based on user input. If you're displaying a person's attributes and allowing the user to make modifications, maybe you pass the object into a single method so that all updates can be applied in one spot.
Either approach can be warranted at different times.
I think the code is more clear and readable when methods don't change objects passed. Especially internal fields of passed object.
This might be needed sometimes. But in general I would avoid it.
Updated based on comment (good point)
I agree with Anthony's answer. There are times when both styles may make sense.
Also, for more readability you can add the LoadName function in person class.
public void App()
{
Person p = new Person();
p.LoadName(); //If you need additional data to set the Name. You can pass that as Parameter
}
You are accessing the data using properties which technically is by a methods. What you are worried is property accessing iVar or internal variable. There reason why it is generally bad to allow access of iVar is because anyone can modify the variables without your knowledge or without your permission, if its through a methods (properties), you have the ability to intercept the message when it get or set, or prevent it from getting read or write, thus it is generally said to be the best practice.
I agree with Ron. Although your particular example could be slightly contrived for posting reasons, I would have a public getter for Name, and a private setter. Pass the name to the constructor, and the Name property will get set there, but afterwards can no longer be modified.
For example:
public class Person
{
public string Name { get; private set; }
public Person( string name)
{
Name = name;
}
}

2 objects, exactly the same (except namespace) c#

I'm using a 3rd party's set of webservices, and I've hit a small snag. Before I manually make a method copying each property from the source to the destination, I thought I'd ask here for a better solution.
I've got 2 objects, one of type Customer.CustomerParty and one of type Appointment.CustomerParty. The CustomerParty objects are actually property and sub-oject exactly the same. But I can't cast from 1 to the other.
So, I need to find a certain person from the webservice. I can do that by calling Customer.FindCustomer(customerID) and it returns a Customer.CustomerParty object.
I need to take that person that I found and then use them a few lines down in a "CreateAppointment" request. Appointment.CreateAppointment takes an appointment object, and the appointment object contains a CustomerParty object.
However, the CustomerParty object it wants is really Appointment.CustomerParty. I've got a Customer.CustomerParty.
See what I mean? Any suggestions?
Why don't you use AutoMapper? Then you can do:
TheirCustomerPartyClass source = WebService.ItsPartyTime();
YourCustomerPartyClass converted =
Mapper.Map<TheirCustomerPartyClass, YourCustomerPartyClass>(source);
TheirCustomerPartyClass original =
Mapper.Map<YourCustomerPartyClass, TheirCustomerPartyClass>(converted);
As long as the properties are identical, you can create a really simple map like this:
Mapper.CreateMap<TheirCustomerPartyClass, YourCustomerPartyClass>();
Mapper.CreateMap<YourCustomerPartyClass, TheirCustomerPartyClass>();
This scenario is common when writing domain patterns. You essentially need to write a domain translator between the two objects. You can do this several ways, but I recommend having an overridden constructor (or a static method) in the target type that takes the service type and performs the mapping. Since they are two CLR types, you cannot directly cast from one to the other. You need to copy member-by-member.
public class ClientType
{
public string FieldOne { get; set; }
public string FieldTwo { get; set; }
public ClientType()
{
}
public ClientType( ServiceType serviceType )
{
this.FieldOne = serviceType.FieldOne;
this.FieldTwo = serviceType.FieldTwo;
}
}
Or
public static class DomainTranslator
{
public static ServiceType Translate( ClientType type )
{
return new ServiceType { FieldOne = type.FieldOne, FieldTwo = type.FieldTwo };
}
}
I'm using a 3rd party's set of
webservices...
Assuming you can't modify the classes, I'm not aware of any way you can change the casting behavior. At least, no way that isn't far, far more complicated than just writing a CustomerToAppointmentPartyTranslator() mapping function... :)
Assuming you're on a recent version of C# (3.5, I believe?), this might be a good candidate for an extension method.
Have you looked at adding a conversion operator to one of the domain classes to define an explicit cast. See the msdn documentation here.
Enjoy!
A simple and very fast way of mapping the types is using the PropertyCopy<TTarget>.CopyFrom<TSource>(TSource source)
method from the MiscUtil library as described here:
using MiscUtil.Reflection;
class A
{
public int Foo { get; set; }
}
class B
{
public int Foo { get; set; }
}
class Program
{
static void Main()
{
A a = new A();
a.Foo = 17;
B b = PropertyCopy<B>.CopyFrom(a);
bool success = b.Foo == 17; // success is true;
}
}
Two classes with exactly the same signature, in two different namespaces, are two different classes. You will not be able to implicitly convert between them if they do not explicitly state how they can be converted from one to the other using implicit or explicit operators.
There are some things you may be able to do with serialization. WCF DataContract classes on one side do not have to be the exact same type as the DataContract on the other side; they just have to have the same signature and be decorated identically. If this is true for your two objects, you can use a DataContractSerializer to "convert" the types through their DataContract decoration.
If you have control over the implementation of one class or the other, you can also define an implicit or explicit operator that will define how the other class can be converted to yours. This will probably simply return a new reference of a deep copy of the other object in your type. Because this is the case, I would define it as explicit, to make sure the conversion is only performed when you NEED it (it will be used in cases when you explicitly cast, such as myAppCustomer = (Appointment.CustomerParty)myCustCustomer;).
Even if you don't control either class, you can write an extension method, or a third class, that will perform this conversion.

Categories

Resources