Implement property with custom attribute - c#

Maybe I'm getting the Concept of Custom Attributes wrong, but I thought this should be something that would be possible:
I'm having a class with a string property. I have multiple derived classes with properties that basically get a sub-string of the baseClass's property
class BaseClass {
public string MyString { get; set;}
}
class FooClass : BaseClass {
public string Part1 { get { return MyString.SubString(0,3); }}
public string Part2 { get { return MyString.SubString(3,5); }}
}
class BarClass : BaseClass {
public string PartA { get { return MyString.SubString(0,4); }}
public string PartB { get { return MyString.SubString(4,1); }}
}
They also have a setters, and the real code is a little bit more complex... But you got the picture.
I would like to not have to implement this a thousand times, so I was thinking of using a custom attribute. So I could do:
class FooClass : BaseClass {
[DataPart(0, Length = 3)]
public string Part1 { get; set; }
[DataPart(3, Length = 5)]
public string Part2 { get; set; }
}
class BarClass : BaseClass {
[DataPart(4, Length = 4)]
public string PartA { get; set; }
[DataPart(4)]
public string PartB { get; set; }
}
I already have Custom Attribute for it:
[global::System.AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
sealed class DataPartAttribute : Attribute
{
public ushort Position { get; private set; }
public ushort Length { get; set; }
public DataByteAttribute(ushort position)
{
Position = position;
}
}
What now?

You need to write code to process your custom DataPartAttribute by using reflection.
perhaps, you should think about using System.ComponentModel.DataAnnotations.
For ex)
[StringLength(100, MinimumLength =30)]
public string Description { get; set; }
you can then use an instance of ObjectValidator to validate your object.

You would need to have the attribute hijack the getter to return something custom, which is not possible to do with .NET alone.
Apparently you can do it with a product called PostSharp (see the answer to this question).
You could put code in the getter to look at the attribute and build the string accordingly, so that every property would have the exact same code. I suspect this is all that PostSharp would do. But it would perform worse than using .Substring in every getter.

Related

Using empty base class just for polymorphism purpose?

I have my ResponseDto which includes a simple string property named Answer.
public string Answer { get; set; }
Now, the requirement came such that I could either be getting an answer as a string, or as an array of int.
I decided to create two classes for this:
public class AnswerType {
public string Answer { get; set; }
}
public class OptionAnswerType {
public int[] AnswerOptionIds { get; set; }
}
I could serialize / deserialize it accordingly.
But to still keep a single response property type, I thought about creating an empty base class:
public class BaseAnswerType { }
public class AnswerType : BaseAnswerType {
public string Answer { get; set; }
}
public class OptionAnswerType : BaseAnswerType {
public Guid[] AnswerOptionIds { get; set; }
}
and change my property in ResponseDto to:
public BaseAnswerType Answer { get; set }
through which via run time, I would be returning either of the two classes.
Is this a bad approach? Any alternate would be greatly appreciated.

How to include properties via composition?

After having to refactor the inheritance chain in my current project for the third time I googled "Inheritance sucks" and found that the problem I'm having is not uncommon and composition is a recommended alternative solution.
I understand how you can use composition to add behavior in form of functions, but I'm having problems to come up with ways to add properties by the same means.
Let's say I want to model tree nodes. Every node has at least two properties: name and description.
class Node {
public string Name { get; set; }
public string Description { get; set; }
}
Other more specific nodes would inherit those properties, like so:
class StructuredNode : Node {
public List<Node> Children { get; set; }
}
How could I achieve similar re-usability of the property code without relying on inheritance and the problems that come with it?
Is there a design pattern for this or do I have to use inheritance in such a case?
Thanks in advance!
Edit:
Examples for the position "composition over inheritance":
ScottLilly
Wikipedia
Codingdelight
Rather then depending on class , you should depend son abstraction (this also one part of making use of composition) so for you case you should do like this
public interface INode {
string Name { get; set; }
string Description { get; set; }
}
class Node : INode {
public string Name { get; set; }
public string Description { get; set; }
}
class StructuredNode : INode {
public string Name { get; set; }
public string Description { get; set; }
public List<INode> Children { get; set; }
}
or you can also do this
//this is something similar to decorator pattern.
class StructuredNode {
private readonly INode _node;
public StructureNode(INode node)
{
_node = node;//now you can reuse function of any class which implements INode
}
public List<INode> Children { get; set; }
}
you should do like this also later on
List<Node> nodes = List<Node>();
StructuredNode sNode = new StructuredNode();
sNode.Children = nodes;
this is possible as all is based on abstraction. and all implementation now make use of INode
or
other solution suggested you in comment is make use of Decorator pattern. If you just want to extend you class without modifying it.
How could I archive similar re-usability of the property code without relying on inheritance and the problems that come with it?
The alternative to using inheritance is either interfaces or composition. However, for properties specifically, you're a bit stuck.
Interfaces cannot contain a default implementation the same way that a base class can. So while you can enforce that your classes use the correct "composed property structure", you can't make reusable methods available without implementing them in every class that implements the interface (or can you? More after the break!)
Composition simply doesn't exist in C# in a way that you can add properties to a class on the fly (unless you are satisfied with a Dictionary<string,string>). There may be some contrived method to technically make it work, but it won't be a good approach.
Interfaces + extension methods.
Extension methods can be used here to replace the reusable logic that you'd find in an inherited base class.
There is one drawback to this: The properties that you wish to access inside the extension methods need to be part of the interface contract and publically accessible.
Other than this drawback, it ticks the box on every other requirement you have.
First, an inheritance-based example:
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
public class PropertyComposedObject
{
public List<Property> Properties { get; set; }
public Property GetProperty(string name)
{
return this.Properties.SingleOrDefault(x => x.Name == name);
}
}
public class Person : PropertyComposedObject
{
}
If we were to use an interface instead, we would lose access to benefits such as a shared GetNode(string) method. You could add it as part of the interface, but each implementing class would then be responsible for implementing that method (leading you to copy/paste the same methods all over the place).
An interface example without extension methods:
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
public interface IPropertyComposedObject
{
List<Property> Properties { get; set; }
Property GetProperty(string name);
}
public class Person : IPropertyComposedObject
{
public List<Property> Properties { get; set; }
public Property GetProperty(string name)
{
return this.Properties.SingleOrDefault(x => x.Name == name);
}
}
But extension methods allows us to define the reusable method once but still access it from every class that implements the interface:
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
public interface IPropertyComposedObject
{
List<Property> Properties { get; set; }
}
public class Person : IPropertyComposedObject
{
public List<Property> Properties { get; set; }
}
public static class IPropertyComposedObjectExtensions
{
public Property GetProperty(this IPropertyComposedObject obj, string name)
{
return obj.Properties.SingleOrDefault(x => x.Name == name);
}
}
My attempt to minimize code duplication:
interface INodeProperties
{
string Name { get; set; }
string Description { get; set; }
}
class NodeProperties : INodeProperties
{
public string Name { get; set; }
public string Description { get; set; }
}
interface INode
{
INodeProperties NodeProps { get; set; }
}
class Node : INode
{
public INodeProperties NodeProps { get; set; } = new NodeProperties();
}
interface IStructuredNode
{
List<Node> Children { get; set; }
}
class StructuredNode: INode, IStructuredNode
{
public INodeProperties NodeProps { get; set; } = new NodeProperties();
public List<Node> Children { get; set; }
}
Downside: One more "hop" to get to the actual Properties ... :(
Have an INode interface, which encapsulates common properties.
This way you should have auto properties, then avoid putting logic in properties' getter and setter, because you can not reuse this logic.
Then repeating auto property definitions is not important and does not affect reusability.
If you need property change notification, it is better to use interceptor libraries such as postsharp.

Using a base class as parameter

I'm sure this is just a matter of me not understanding something completely obvious, but I seem to be hopefully stuck on this.
I have an abstract base class that is inherited by a large amount of other classes, to maintain security information across my application. I'll simplify for this question though.
public abstract class ModelBase
{
public int UserID { get; set; }
public string UserName { get; set; }
}
public class SpecificModel : ModelBase
{
public int specificInt { get; set; }
public string specificString { get; set; }
}
In this case, about 30 different classes all inherit from ModelBase.
I would like to create a method that can accept any object who's class inherits from ModelBase. So I created something like this:
public bool TestIt (ref ModelBase BaseModel)
{
BaseModel.UserID = 10;
BaseModel.UserName = "Evan";
return true;
}
However, if I try to pass in an object of type SpecificModel, I get an error.
SpecificModel hiThere = new SpecificModel();
hiThere.specificInt = 5;
hiThere.specificString = "Oh well";
bool retVal = TestMethods.TestIt(ref hiThere);
The error I see on the last line is: The best overloaded method match for 'TestMethods.TestIt(ref ModelBase)' has some invalid arguments
What am I not "getting" here?
Thanks
You have it right, except you don't want to be passing by ref (likely the source of your error). Your class is already a reference type, you probably don't need to pass a reference to it. Given the function definition in the question;
public bool TestIt (ModelBase BaseModel)
{
BaseModel.UserID = 10;
BaseModel.UserName = "Evan";
return true;
}
Will be perfect (except for the weird "always return true" but perhaps thats because this is demo code).
whats the error it throwing?
I have tried it myself its nothing look wrong in your code. might be your calling mechanism is not correct. here is the sample code.
class Program
{
static void Main(string[] args)
{
ModelBase sp = new SpecificModel2();
TestIt(ref sp);
}
public static bool TestIt(ref ModelBase BaseModel)
{
BaseModel.UserID = 10;
BaseModel.UserName = "Evan";
return true;
}
}
public abstract class ModelBase
{
public int UserID { get; set; }
public string UserName { get; set; }
}
public class SpecificModel : ModelBase
{
public int specificInt { get; set; }
public string specificString { get; set; }
}
public class SpecificModel2 : ModelBase
{
public int specificInt { get; set; }
public string specificString { get; set; }
}
}

.getJson call not working with objects that use inheritence

first post... Normally I'm able to search and find answers to my problems, but this time I am not able to. I have an object that uses a bunch of other objects:
[DataContract]
public class CoolStuff
{
[DataMember]
public Field[] CoolField { get; set; }
public CoolStuff()
{
CoolField = SetCoolField();
}
private Field[] SetCoolField()
{
return new Field[]
{
new Field("Project Information", "ProjectInformation"),
new Field("Resource Information", "ResourceInformation"),
}
}
}
[DataContract]
public class Field
{
[DataMember]
public string Prompt { get; set; }
[DataMember]
public string Value { get; set; }
[DataMember]
public bool IsLocked { get; set; }
public Field(string prompt, string value = "n/a", bool isLocked = false)
{
Prompt = prompt;
Value = value;
IsLocked = isLocked;
}
}
I call my constructors from a service, and this works fine and dandy when I try to serialize it with $.getJSON(/Service.svc/coolstuff/' + id, loadCoolStuff);
The problem is, when I make my Field class inherit from another class, that .getJson call fails without really giving me a reason why.
[DataContract]
public class CoolStuff
{
[DataMember]
public FieldBase[] CoolField { get; set; }
public CoolStuff()
{
CoolField = SetCoolField();
}
private FieldBase[] SetCoolField()
{
return new FieldBase[]
{
new Field("Project Information", "ProjectInformation"),
new Field("Resource Information", "ResourceInformation"),
}
}
}
[DataContract]
public class FieldBase
{
}
[DataContract]
public class Field : FieldBase
{
[DataMember]
public string Prompt { get; set; }
[DataMember]
public string Value { get; set; }
[DataMember]
public bool IsLocked { get; set; }
public Field(string prompt, string value = "n/a", bool isLocked = false)
{
Prompt = prompt;
Value = value;
IsLocked = isLocked;
}
}
Can someone please explain why with ^ this code, my call to .getJSON fails? I'm really stuck here. Thanks so much!
OK, reading between the lines I've deduced you're using WCF for this web service. The use of DataContract attributes and url ending in .svc make that clear enough. That's relevant, because this issue seems particular to the way WCF serializes. As mentioned in my above comments, the same class structure has no problems in ASP.NET Web API using the default Newtonsoft JSON serializer.
What you need here is the KnownType attribute to properly define derived types for serialization.
This article offers some straight-forward examples. This one has a bit more detail on the concepts.
For the example you've provided, you'd need to decorate the FieldBase definition like this:
[DataContract]
[KnownType(typeof(Field))]
public class FieldBase
{
}
Note that this will add an extra field to your JSON, like "__type":"Field:#MyTestWebProject". You could just ignore that, or go hunting for ways to get rid of it if it bothers you. I wouldn't guarantee it's possible though.

C# Attributes: One Attribute to Rule Them All?

Is it possible to assign an attribute on a property and use it in order to assign other attributes - doing so without using reflection?
The code:
public class CashierOut : BaseActivity
{
[Description("Flag indicates whether break to execution.")]
[DefaultValue(false)]
[MyCustomAttribute(ParameterGroups.Extended)]
public bool CancelExecution { get; set; }
[Description("Flag indicates whether allow exit before declation.")]
[DefaultValue(true)]
[MyCustomAttribute(ParameterGroups.Extended)]
[DisplayName("Exit before declaration?")]
public bool AllowExitBeforeDeclare { get; set; }
}
I would like to do something like this:
public class CashierOut : BaseActivity
{
[MyResourceCustom("CashierOut.CancelExecution")]
public bool CancelExecution { get; set; }
[MyResourceCustom("CashierOut.AllowExitBeforeDeclare")]
public bool AllowExitBeforeDeclare { get; set; }
}
public sealed class MyResourceCustom : Attribute
{
public string ResourcePath { get; private set; }
public ParameterGroupAttribute(string resourcePath)
{
ResourcePath = resourcePath;
// Get attributes attributes value from external resource using the path.
}
}
Attributes simply add meta data to the members they are defined on - by themselves they do nothing.
You will have to use reflection in order to produce some behaviour depending on the attribute values.
This is how all attributes work - some of the tooling is aware of some attributes (like the compiler and the ConditionalAttribute), but this is still done via reflection.
Look into Aspect Oriented Programming. You can use tools like postsharp to modify your code either at compile or runtime.
You could add a member to MyResourceCustom that wraps Description, DefaultValue, and MyCustomAttribute in an immutable instance (maybe even a static global, if it can be the same for everyone).
public class MyResourceCustom : Attribute {
public MyResourceCustomDescriptor Descriptor { get; private set; }
public MyResourceCustom(MyResourceCustomDescriptor descriptor)
: base() {
Descriptor = descriptor;
}
public class MyResourceCustomDescriptor {
public string Description { get; private set; }
public bool DefaultValue { get; private set; }
public ParameterGroups ParameterGroup { get; private set; }
public MyResourceCustomDescriptor(string path) {
// read from path
}
}
public class MyAdvancedResouceCustomDescriptor : MyResourceCustomDescriptor {
public string DisplayName { get; private set; }
// etc...
}
When you fetch the attribute you can get its Descriptor property and read the values.
As a sidenote, you should name it IsDefaultValue.

Categories