1

I have a User class (there are also several subclasses) that is used throughout a large system. In very certain situations, I need to attach a few extra properties to the class. For several reasons, however, I do not want them at other times.

Creating a subclass does not seem possible since I would not be able to downcast my objects to this derived type. I also can't use a copy constructor to construct these subtype objects, as I don't know if my object has inherited properties from some subclass.

A simplified example of what I need:

class User 
{
  public string Firstname { get; set; }
}

A property like:

public string FirstLetterOfFirstName { get { return Firstname.Substring(0, 1); } }

How would you give the objects of type User this kind of property?

I tried deep cloning but I still only get a User object that I still cannot cast to my type with the property. Is this even possible in any way?

I don't want to use methods (extension methods included) as I elsewhere use these properties to extract relevant data from the object.

SamiHuutoniemi
  • 1,576
  • 2
  • 16
  • 35

3 Answers3

3

In this case it could be an extension method:

public static class UserExtensionMethods
{
    public static string FirstLetterOfFirstName(this User user)
    {
        return user.FirstName.Substring(0, 1);
    }
}

Then call it:

user.FirstLetterOfFirstName();

Other options include the ExpandoObject, where you can add Actions and Func dynamically.

A sample:

dynamic x = new ExpandoObject();
x.User = new User();
x.FirstLetterOfFirstName = new Func<string>(() => x.User.FirstName.Substring(0, 1));

As you see, it isn't getting clearer. Use extension methods. It's the better way.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • 2
    The method must be static. – Simon Belanger Dec 10 '14 at 15:55
  • The reason I want them as properties to start with is that I use a database to direct a format of a string (to build an email), based on these properties. A method then extracts properties based on name from whatever User object (or subtype) I provide. Don't know if I can do that with extension methods. In other words. I do want properties - not methods. – SamiHuutoniemi Dec 10 '14 at 15:57
  • 1
    @SamiHuutoniemi: Properties or methods, it all doesn't matter too much IMHO. There is not something like 'extension properties' to extension methods is the way to go. – Patrick Hofman Dec 10 '14 at 16:00
  • @SamiHuutoniemi Can't be done with extension methods as the method are not part of the class definition (through reflection). I guess you could use another object to transform your `User` base class and then work on that object. – Simon Belanger Dec 10 '14 at 16:00
  • @PatrickHofman Can't use expando objects. The User object is actually a Linq2Sql object. – SamiHuutoniemi Dec 10 '14 at 16:11
  • @SamiHuutoniemi: Okay, the `ExpandoObject` is just a wrapper. As said, extension methods is the way to go. – Patrick Hofman Dec 10 '14 at 16:11
  • @PatrickHofman I extract the property values from Objects using reflection. Can I do this with extension methods? – SamiHuutoniemi Dec 10 '14 at 16:13
  • @SamiHuutoniemi: No problem. As long you have a `User` instance, it will work. Don't matter how you extract the data. – Patrick Hofman Dec 10 '14 at 16:13
1

You could use extension methods for that kind of behaviour, but they will not be accessible as properties, but as methods:

public static class UserExtensions
{
    public static string FirstLetterOfFirstName(this User user) 
    {
        return user.FirstName.Substring(0,1);
    }
}

// In your code

User u = new User();
u.FirstLetterOfFirstName();

As a side note, the extension method will only be able to access public members of the extended class / structure and internal members if they are in the same assembly.

Simon Belanger
  • 14,752
  • 3
  • 41
  • 35
0

Extention methods are the way to go. Those can be internal to the assembly where you need it and not available in outer world.

You can also have explicit implementation of internal interface, so that you'll only be able to use the functionality of this interface inside the assembly

Andrew
  • 3,648
  • 1
  • 15
  • 29