Yesterday I came across a problem. I was asked to write a rest service which exposes all properties of a class. The consumers would all consume different properties and when submitting they would all send different subsets of them.
For example sake lets call the contract company.
class Company{
public string Address {get;set;}
public string CompanyNumber {get;set;}
public string Turnover {get;set;}
public string Employees {get;set;}
}
Lets say we have two known systems which would like to sync the Company class.
System 1 deals with accounting and wants to read Address and Update Turnover.
System 2 deals with hr and wants to read Address and update Employees.
Now normally when faced with this problem one would write lots of interfaces each with a tailored contract to suit the end system. However I have been told this is not what they want. Instead if the property is supplied in the JSON it must be set.
The problem is when deserialising the class Company from JSON if the property is not supplied the property is null, this will then when mapped to the database classes overwrite the data.
The solution I came up with was to create an Optional struct like Nullable but where null can also be a valid value.
When deserialising this struct can track if the property was set, and therefore provided in the JSON. I can then check this when mapping from the DTO to the database class and map only when the property is set.:)
https://dotnetfiddle.net/QmHtSW
public interface IOptional
{
bool HasBeenSet { get; }
}
public struct Optional<T> : IOptional
{
internal readonly T Val;
public Optional(T value)
{
Val = value;
HasBeenSet = true;
}
public Optional(Optional<T> value)
{
Val = value.Value;
HasBeenSet = value.HasBeenSet;
}
public bool HasBeenSet { get; }
public override bool Equals(object obj)
{
return obj.Equals(Val);
}
public override int GetHashCode()
{
return Val.GetHashCode();
}
public static implicit operator T(Optional<T> optional)
{
return optional.Val;
}
public static implicit operator Optional<T>(T optional)
{
return new Optional<T>(optional);
}
public T Value => Val;
}
and my AutoMapper mapping profile
CreateMap<TRestObject, TDomainObject>()
.ForAllMembers(mo=>mo.Condition(f =>
{
var opt = f.SourceValue as IOptional;
return opt==null || opt.HasBeenSet;
}));
Related
This is probably a stupid question, but just in case....
We have a 3rd party package with weird models like:
public partial class CountingDevice
{
public int countingDeviceNo { get; set; }
public string countingDeviceName { get; set; }
public string obis { get; set; }
public int integralPart { get; set; }
public bool integralPartFieldSpecified;
public int fractionalPart { get; set; }
public bool fractionalPartFieldSpecified;
public double value { get; set; }
public bool valueFieldSpecified;
public bool offPeakFlag { get; set; }
public bool offPeakFlagFieldSpecified;
public ExpectedMeterReading expectedMeterReading { get; set; }
// snipped for brevity
}
You'll notice that sometimes there are pairs of fields like integralPart and integralPartFieldSpecified.
Here is the problem: If I simply assign some value to integralPart but do not set integralPartFieldSpecified = true, the value of integralPart will be completely ignored causing the solution to fail.
So when mapping our own models to this madness, I need to litter the code with constructs like:
if (IntegralPart != null)
{
countingDevice.integralPartSpecified = true;
countingDevice.integralPart = (int)IntegralPart!;
}
Both in the interest of reducing lines of code and not stumbling over a minefield, I would like to do any one of the following:
A. Overload the = operator so it will automatically check for a property which is a boolean and has "Specified" concatenated to the current property's name. If such a property exists, it will be assigned true when the value is assigned; if not, then assignment will operate as normal. Ideally, it should be "smart" enough to assign "...Specified" to false if the value assigned is null/default/empty.
B. Create some customer operator which will do the same as A.
C. Create some method which I could invoke in a concise and preferably typesafe way to do the same.
Is this possible?
If so, how?
To make it clear: I need to build quite a few wrappers.
I don't want to repeat this logic for every field and worry about missing some fields which it applies to.
I want a generic way of assigning both fields at once if the "Specified" field exists and being able to do assignments in exactly the same way if it does not exist.
not stumbling over a minefield
Encapsulate the minefield.
If you don't control this 3rd party DTO then don't use it throughout your domain. Encapsulate or wrap the integration of this 3rd party tool within a black box that you control. Then throughout your domain use your models.
Within the integration component for this 3rd party system, simply map to/from your Domain Models and this 3rd party DTO. So this one extra line of code which sets a second field on the DTO only exists in that one place.
Another (expensive) solution would be to write a method that takes in an object, a property name, and the new property value. You can then use reflection to both set the property value for the specified property, as well as search for the bool field that you want to set (if it exists).
Note that you need to pass the correct type for the property. There's no compile-time checking that you're passing a double instead of a string for the value property, for example.
Below I've created an extension method on the object type to simplify calling the method in our main code (the method becomes a member of the object itself):
public static class Extensions
{
// Requires: using System.Reflection;
public static bool SetPropertyAndSpecified(this object obj,
string propertyName, object propertyValue)
{
// Argument validation left to user
// Check if 'obj' has specified 'propertyName'
// and set 'propertyValue' if it does
PropertyInfo prop = obj.GetType().GetProperty(propertyName,
BindingFlags.Public | BindingFlags.Instance);
if (prop != null && prop.CanWrite)
{
prop.SetValue(obj, propertyValue, null);
// Check for related "FieldSpecified" field
// and set it to 'true' if it exists
obj.GetType().GetField($"{propertyName}FieldSpecified",
BindingFlags.Public | BindingFlags.Instance)?.SetValue(obj, true);
return true;
}
return false;
}
}
After you add this class to your project, you can do something like:
static void Main(string[] args)
{
var counter = new CountingDevice();
// Note that 'valueFieldSpecified' and `integralPartFieldSpecified'
// are set to 'false' on 'counter'
// Call our method to set some properties
counter.SetPropertyAndSpecified(nameof(counter.integralPart), 42);
counter.SetPropertyAndSpecified(nameof(counter.value), 69d);
// Now 'valueFieldSpecified' and 'integralPartFieldSpecified'
// are set to 'true' on 'counter'
}
You cannot overload the = operator in C#.
You can just use custom properties and set the "FieldSpecified" fields in the setters e.g.
private int _integralPart;
public int integralPart
{
get { return _integralPart; }
set
{
_integralPart = value;
integralPartFieldSpecified = true;
}
}
public bool integralPartFieldSpecified;
Update
If you want a generic solution you can use a generic class for properties that you want to achieve the specified behaviour with e.g.
public class ValueWithSpecifiedCheck<T>
{
private T _fieldValue;
public T FieldValue
{
get
{
return _fieldValue;
}
set
{
_fieldValue = value;
FieldSpecified = true;
}
}
public bool FieldSpecified { get; set; }
}
public class Data
{
public ValueWithSpecifiedCheck<int> IntegralPart { get; set; }
}
Then the class/property would be used as following:
public static void Main()
{
var data = new Data();
data.IntegralPart = new ValueWithSpecifiedCheck<int>();
data.IntegralPart.FieldValue = 7;
Console.WriteLine(data.IntegralPart.FieldSpecified);// Prints true
}
If you implement a generic solution and add implicit conversion operators, it's quite convenient to use.
Here's a sample Optional<T> struct (I made it a readonly struct to ensure immutable mechanics):
public readonly struct Optional<T> where T : struct
{
public Optional(T value)
{
_value = value;
}
public static implicit operator T(Optional<T> opt) => opt.Value;
public static implicit operator Optional<T>(T opt) => new(opt);
public T Value => _value!.Value;
public bool Specified => _value is not null;
public override string ToString() => _value is null ? "<NONE>" : _value.ToString()!;
readonly T? _value;
}
You could use that to implement your CountingDevice class like so:
public partial class CountingDevice
{
public int countingDeviceNo { get; set; }
public string countingDeviceName { get; set; }
public string obis { get; set; }
public Optional<int> integralPart { get; set; }
public Optional<int> fractionalPart { get; set; }
public Optional<double> value { get; set; }
public Optional<bool> offPeakFlag { get; set; }
// snipped for brevity
}
Usage is quite natural because of the implicit conversions:
public static void Main()
{
var dev = new CountingDevice
{
integralPart = 10, // Can initialise with the underlying type.
value = 123.456
};
Console.WriteLine(dev.fractionalPart.Specified); // False
Console.WriteLine(dev.integralPart.Specified); // True
Console.WriteLine(dev.value); // 123.456
Console.WriteLine(dev.value.ToString()); // 123.456
Console.WriteLine(dev.fractionalPart.ToString()); // "<NONE>"
dev.fractionalPart = 42; // Can set the value using int.
Console.WriteLine(dev.fractionalPart.Specified); // True
Console.WriteLine(dev.fractionalPart); // 42
var optCopy = dev.offPeakFlag;
Console.WriteLine(optCopy.Specified); // False
dev.offPeakFlag = true;
Console.WriteLine(dev.offPeakFlag.Specified); // True
Console.WriteLine(optCopy.Specified); // Still False - not affected by the original.
Console.WriteLine(optCopy); // Throws an exception because its not specified.
}
You might also want to use optional reference types, but to do that you will need to declare a generic with the class constraint:
public readonly struct OptionalRef<T> where T : class
{
public OptionalRef(T value)
{
_value = value;
}
public static implicit operator T(OptionalRef<T> opt) => opt.Value;
public static implicit operator OptionalRef<T>(T opt) => new(opt);
public T Value => _value ?? throw new InvalidOperationException("Accessing an unspecified value.");
public bool Specified => _value is not null;
public override string ToString() => _value is null ? "<NONE>" : _value.ToString()!;
readonly T? _value;
}
Personally, I think that's a bit overkill. I'd just use nullable value types, int?, double? etc, but it depends on the expected usage.
C# doesn't allow overloading the = operator (unlike eg C++). However, your suggestion C should work. It's a bit of a hassle, too, since you'll have to write a bunch of methods, but you could write an extension method such as
public static class Extensions
{
public static void UpdateIntegralPart(this CountingDevice dev, double value)
{
dev.integralPart = value;
dev.integralPartSpecified = true;
}
}
Then you can call
countingDevice.UpdateIntegralPart(1234);
I'm building a parser for some data that's given as XML, something similar to:
Get file in path %windir%\system32\calc.exe and retrieve it's CreationTime
The small problem that I have is that the type of object that I'm retrieving (FileInfo in example above) and the data type of the property I'm reading (CreationTime which is DateTime in example above) isn't always the same.
For example: on a FileInfo object alone I could be asked for:
bool Exists
DateTime CreationTime
DateTime LastWriteTime
long Size
Version Version
Other object types could be things like FolderInfo, RegistryKey and RegistryValue
With that in mind, I created the following code:
public interface IPropertyRetriever<out T>
{
public string Name { get; }
public Property Property { get; }
public T RetrieveProperty();
}
public enum Property
{
Count,
DateCreated,
DateModified,
RegistryKeyExists,
RegistryValueExists,
Size,
Value,
Version
}
public class FilePropertyRetriever<T> : IPropertyRetriever<T>
{
public FilePropertyRetriever(string name, Property property, string path, bool is64Bit)
{
Name = name;
Property = property;
Path = path;
Is64Bit = is64Bit;
}
public string Name { get; }
public Property Property { get; }
public string Path { get; }
public T RetrieveProperty()
{
var file = ...
// Do something to retrieve FileInfo,
// assumes if it got to code below FileInfo.Exists is true
return (T) (object) (Property switch
{
Property.Count => file.Exists,
Property.DateCreated => file.CreationTime,
Property.DateModified => file.LastWriteTime,
Property.Size => file.Length,
Property.Version => Version.TryParse(FileVersionInfo.GetVersionInfo(Path).ProductVersion,
out var version)
? version
: null
});
}
}
I know that my T RetrieverProperty() method isn't exactly very good programming - I'm telling my method what type I want it to return when in fact it knows already and using generics to cast to the correct type (and boxing it first if DateTime/long/int), but I really can't think of a better way of doing this.
Any suggestions on how to improve this?
PS: The reason why the RetrieveProperty() accepts no parameters and instead uses properties is because the device where the object is created and where the method are run is not the same, the object is serialised and sent over.
why can't IPropertyRetriever just be this:
public interface IPropertyRetriever
{
public string Name { get; }
public int Count {get;}
public DateTime DateCreated {get;}
public DateTime DateModified {get;}
public bool RegistryKeyExists {get;}
public bool RegistryValueExists {get;}
public long Size {get;}
//etc
}
And call it something different IFileInformation. Or have different interfaces returned for different objects with a base interface as not all the above properties are relevant to all objects.
I have a class say Base Which contains a Property say Id
public abstract class Base
{
public abstract int Id { get; }
}
This abstract class has many concrete derived classes. e.g;
public class Concrete: Base
{
public override int Id
{
get { return importChangekeyLogId; }
}
}
Also In my code solution, there are places where this Property Value is stored in a local variable or passed as a parameter to the method. Check below example where local variable id stores property value and SampleChild2 method accepts int which is the value of Property Id.
public int Sample1(Concrete obj)
{
int id = obj.Id;
SmapleChild2(obj.Id);
return id;
}
public void SmapleChild2(int id)
{
}
Requirement: The above property is just an example we have many such kinds of properties and the estimated time if done manually is 38 days. Therefore, I want to write a utility using Roslyn Through which I can change the data type of Properties to long and also I could find all the references of Properties and update the local variable data types and method signatures. So the final code should be like
public abstract class Base
{
public abstract long Id { get; }
}
public class Concrete: Base
{
public override long Id
{
get { return importChangekeyLogId; }
}
}
public long Sample1(Concrete obj)
{
long id = obj.Id;
SmapleChild2(obj.Id);
return id;
}
public void SmapleChild2(long id)
{
}
Code done till now: I am able to change the abstract class property data type to long using code like below
public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
{
PredefinedTypeSyntax _longType = SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.LongKeyword)).WithTrailingTrivia(SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, " "));
if (node.Type.ToString() == "int")
{
var propertyName = node.Identifier.ValueText;
if (propertyName == "Id")
{
return node.ReplaceNode(node.Type, _longType);
}
}
return node;
}
I am able to find all the references where the property is being used from the below code. But I am not able to find a way to update the local variable's data type and method signatures which deal with the property value.
if (propertyName == "Id")
{
var propertySymbol = (IPropertySymbol)_semanticModel.GetDeclaredSymbol(node);
var references = SymbolFinder.FindReferencesAsync(propertySymbol, this._solution).Result;
}
I've been looking into rules engines and such, but I really am not sure where to start. This is more for experimentation, but I'd like to implement something like this for work in the future. Basically, I have an application where a user submits a form and populates a POCO object with several properties. I want the administrator of the application to be able to define rules based on the properties of said object and store them in a relational database. When the form is submitted, I would then make a decision based on the user defined rules. For example, the admin can go into the application and define rules like following:
if (typeID == 4 && request.benchMarkScore < 10) {
request.denied = true;
request.denyReasons.Add("Score too low for this product");
}
Here's my POCO Object example:
class Request
{
public int benchMarkScore { get; set; }
public int typeID { get; set; }
public double rate { get; set; }
public bool isEligable { get; set; }
public bool denied { get; set; }
public List<string> denyReasons { get; set; }
public Dictionary<string, double> adjustments;
}
Granted I know this is an overly simplified example, but I come across many situations where I users could benefit from this functionality in my applications. I'm not looking for a complete solution, but instead an idea of where to start.
There are a number of ways you could go about this. One suggestion would be to leverage reflection itself, and allow admins to apply a rule. I'm going to keep this simple, but a rule would consist of:
A bunch of properties, operands, and values
The reason(s) for denial.
So let's define that. I am going to keep this simple and just handle equality, you can define additional ones:
public enum Operand
{
Equals
}
Now, we can define an interface called IRule. I am defining an interface so that in the future, you could potentially put special, more complicated, rules in.
public interface IRule<TPOCO> where TPOCO : class
{
bool IsValid(TPOCO poco);
}
And now we'll define our Rule class (Note: this doesn't handle indexed properties):
public class PropertyCompareRule : IRule<Request>
{
private sealed class PropertyCompare
{
public string PropertyName {get; set; }
public Operand Operand {get; set; }
public object Value {get; set;}
public string Reason {get; set; }
}
private List<PropertyCompare> _comparers = new List<PropertyCompare>();
public bool IsValid(Request poco)
{
bool isValid = true; // let's be optimistic!
PropertyInfo[] properties = poco.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where((property) => property.GetIndexParameters().Length == 0 && property.CanRead).ToArray();
foreach(var property in properties)
{
foreach(var comparer in _comparers)
{
bool localIsValid;
if(comparer.PropertyName == property.Name)
{
object val = property.GetValue(poco, null);
switch(comparer.Operand)
{
case Operand.Equals:
{
localIsValid = object.Equals(val, property.Value);
break;
}
}
if(!localIsValid)
{
poco.denyReasons.Add(comparer.Reason);
isValid = false;
}
}
}
}
return isValid;
}
public void AddComparer(string propertyName, Operand op, object value, string reason)
{
_comparers.Add(new PropertyCompare() { PropertyName = propertyName, Operand = op, Value = value, Reason = reason });
}
}
It wouldn't be difficult for you to be able to persist the property name, operand, and value details in a database or other such storage. Assuming we fleshed out our enum above, we could conceivably do:
PropertyCompareRule rule = new PropertyCompareRule();
rule.AddComparer("typeID", Operand.Equal, 4, "Reason 1");
rule.AddComparer("benchMarkScore", Operand.LessThan, 10, "Reason 2");
bool valid = rule.IsValid(somePocoInstance);
Edit: Some notes
I use a localIsValid rather than bailing out at the first opportunity. You can change this if you want, but the idea is that it allows a single rule to have multiple points of deniability. This may or may not be what you wish - but it's easy enough to refactor the code so that it bails out the moment a single property comparison fails.
This is a nit-pick, but generally C# style-guidlines dictate properties shouldn't be camel-caps... but that's entirely up to you at the end of the day :)
As I understand you, you are looking for some kind of a scripting system for business rules. I found this blog post where some scripting environment are mentioned.
You can also create assemblies on the fly like mentioned here: https://stackoverflow.com/a/4181855/1229622.
I tried to search for an answer for this problem but could not find much, most probably because I do not know how to look for it properly, so here it goes. All help is very much appreciated.
With the base class that looks like
abstract public class Property
{
private String name;
public Property(String propertyName)
{
name = propertyName;
}
public String Name
{
get { return name; }
}
abstract public override String ToString();
}
And derived classes that look like
public class StringProperty : Property
{
private String value; // different properties for different types
public StringProperty(String propertyName, String value) : base(propertyName)
{
this.value = value;
}
public String Value // different signature for different properties
{
get { return value; }
}
public override String ToString()
{
return base.Name + ": " + value;
}
}
During runtime, the function receives a collection of "Property" objects. What do I need to do to be able to obtain the "Value" of each? Do I need to have a big if statement to query the type of each "Property" object? If not, is there a more elegant solution?
I tried to define an abstract "Value" property to be overridden but since the return types are different, it did not work. I also tried playing with shadowing the "Value" property, but I could not make it work. The idea of using an COM-like Variant does not sound very appropriate, either.
Thanks a lot in advance.
EDIT:
I should have added details as to what I am trying to do. The properties are displayed in a Winforms app. Different "TextBox"es represent different properties and are filtered for proper input (depending on the type). The updated values are read back and stored. The container object will be serialized into JSON and deserialized on an Android and iPhone client and eventually these values will be passed into a layer running native C++ code doing OpenGL stuff. I don't know in advance the kind of all needed properties so as the middleman, I wanted to make my code as robust as possible while being able to feed the OpenGL engine.
You can use a generic class:
public class AnyProperty<T> : Property
{
private T value;
// ... etc
I'd really recommend making the base class an Interface by now:
public interface IProperty
{
public String Name { get; }
}
public class Property<T> : IProperty
{
public Property(String name, T value)
{
Name = name;
Value = value;
}
public String Name { get; private set; }
public T Value { get; private set; }
public override String ToString()
{
return string.Format("{0}: {1}", Name, Value)
}
}
Here is sample usage:
var intProp = new Property<int> ("age", 32);
var strProp = new Property<string> ("name", "Earl");
var enumProp = new Property<ColorEnum> ("eye color", ColorEnum.Magenta);
To make the construction even simpler, you could have a factory method:
public static Property<T> MakeProperty(string name, T value)
{
return new Property<T>(name,value);
}
var intProp = MakeProperty("age", 32);
var strProp = MakeProperty("name", "Earl");
var enumProp = MakeProperty("eye color", ColorEnum.Magenta);
Not necessarily recommended, and a bit OT:
You could make it even funkier with an extension method:
public static Property<T> AsProp<T>(this T value, string name)
{
return new Property<T>(name,value);
}
var intProp = 32.AsProp("age");
var strProp = "Earl".AsProp("name");
var enumProp = ColorEnum.Magenta.AsProp("eye color");
You would have to simply use the object type. What are you trying to accomplish? The problem here isn't the structure of your classes, it's the function that receives the collection of Property objects. It's impossible to even cast something to an unknown type, since you don't know what type of variable it needs to be stored in.
So basically, your Property.Value property needs to be of type object. In your method that uses the Property objects, you need to do something with them, and what you're doing will decide how it should be structured. Are you printing values out? Have a *Value class inheriting from an abstract PropertyValue class and override ToString() to return an appropriate string represention.
I made a few changes to your sample code and got this result...
abstract public class Property
{
private readonly String _name;
public Property(String propertyName)
{
_name = propertyName;
}
public String Name
{
get { return _name; }
}
abstract public override String ToString();
}
public class StringProperty : Property
{
private readonly dynamic _value; // different properties for different types
public StringProperty(String propertyName, dynamic value)
: base(propertyName)
{
this._value = value;
}
public dynamic Value // different signature for different properties
{
get { return _value; }
}
public override String ToString()
{
return base.Name + ": " + _value;
}
}
static void Main(string[] args)
{
StringProperty sp = new StringProperty("A double", 3.444);
StringProperty sp2 = new StringProperty("My int", 4343);
StringProperty sp3 = new StringProperty("My directory", new DirectoryInfo("Some directory"));
StringProperty sp4 = new StringProperty("My null", null);
Console.WriteLine(sp);
Console.WriteLine(sp2);
Console.WriteLine(sp3);
Console.WriteLine(sp4);
}
}
Values are properly printed to the console in the expected way.
It would require a bit of a rethink, but have you considered using the dynamic type (introduced in .net4)
Doesn't really solve your problem, but sidespteps it.
Your properties can bascically just be a
Dictionary<String, dynamic>
, the gotcha is they don't get evaluated until runtime, so you get no compiler support for typing.
so given you want
int SomeValue = MyProperties[SomePropertyName] + 10;
So if
MyProperties[SomePropertyName] = 10; // all is good
if its 76.52 or Fred, the addition will throw an exception at the point it executes.
Code is much simpler and cleaner, no extra casting and the amount of scaffolding required is minimal, BUT, you'll need to unit test code that uses the dictionary extensively and religiously.