I know the fact that C# doesn't support properties with arguments except the default properties. But I think still it's nice to have such feature in some situations. As an example, an application might have settings which are specific to the language currently used. So such settings property may look like this.
settings.IsContentDownloaded["en-US"] = true;
Event thought this doesn't support by default, we can come up with a workaround to simulate this with other great feature available in the language. But the problem is what is the best workaround which provide a generalized approach to this problem.
I have my own workaround for this and I have shared it as an answer. But I'm looking for a better approach or any improvement to my approach.
create a dictionary where the keys are your strings such as "en-US" and the values are a bool:
Dictionary<string, bool> aaa = new Dictionary<string, bool>();
aaa.Add("en-US", true);
if(aaa["en-US"].Equals(true))
{
}
Its an interesting question, here is a method I came up with:
public class LocalizableSetting<T> : IEnumerable<KeyValuePair<string, T>>
{
private Dictionary<string, T> _values;
public T this[string cultureName]
{
get { return _values[cultureName]; }
set
{
_values[cultureName] = value;
}
}
public IEnumerator<KeyValuePair<string, T>> GetEnumerator()
{
return _values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _values.GetEnumerator();
}
public static implicit operator T(LocalizableSetting<T> value)
{
return value[CultureInfo.CurrentCulture.Name];
}
public static implicit operator LocalizableSetting<T>(T value)
{
var setting = new LocalizableSetting<T>();
setting[CultureInfo.CurrentCulture.Name] = value;
return setting;
}
}
Here LocalizableSetting stores localized values in an internal dictionary, which is really nothing special, however I added a feature that allows it to be used like normal properties as well, the implicit conversion operators.
This does take some tricks to use though, in order to properly use it in a class, you cannot use auto-properties, since you have to merge the two on a set, not overwrite it, so here is an example of how to use it in a class:
public class SomeLocalizableClass
{
//Explicitly declare the backing field for the property!
private LocalizableSetting<int> _intSetting = new LocalizableSetting<int>();
public LocalizableSetting<int> IntSetting
{
get { return _intSetting; }
set
{
//Merge, don't overwrite
foreach (var kvp in value)
_intSetting[kvp.Key] = kvp.Value;
}
}
}
Notice that in the set method, it iterates through the values and either overwrites the current one or adds a new one (with the help of the indexer).
So, this allows you to do something like this:
public class SomeConsumerClass
{
public void SomeMethod()
{
SomeLocalizableClass c = new SomeLocalizableClass();
c.IntSetting["fr-FR"] = 4; //Sets the french setting
c.IntSetting = 10; //Sets the current culture setting
int multipleSetting = c.IntSetting * c.IntSetting;
}
}
Where multipleSetting will be the multiple of the current culture values for that property due to the implicit conversion from LocalizableSetting<int> to int. The c.IntSetting = 10 causes an implicit conversion from the source type (int) to a LocalizableSetting<int> and then assigns it to the property, this is why a merge is needed instead of an overwrite.
There are a couple (big) holes that I left here, namely that the property should return some default value if the value for that culture is not found (currently it will throw an exception). But it shows one method of solving this issue.
I have used dictionary named _settingsRepositoty to store settings, but it might be anything which use to store setting based on the application type.
public class Settings
{
private Dictionary<string, object> _settingsRepository = new Dictionary<string, object>();
private LanguageSpecificPropertyFactory _factory;
public Settings()
{
_factory = new LanguageSpecificPropertyFactory(this);
}
public LanguageSpecificProperty<bool> IsContentDownloaded
{
get
{
return _factory.GetLanguageProperty("IsContentDownloaded", false);
}
}
private void Set<T>(string propertyName, string lang, T val)
{
string fullPropertyName = string.Format("{0}_{1}", propertyName, lang);
_settingsRepository[fullPropertyName] = val;
}
private T Get<T>(string propertyName, string lang, T defaultValue)
{
string fullPropertyName = string.Format("{0}_{1}", propertyName, lang);
if (!_settingsRepository.ContainsKey(fullPropertyName))
{
_settingsRepository[fullPropertyName] = defaultValue;
}
return (T)_settingsRepository[fullPropertyName];
}
public class LanguageSpecificProperty<T>
{
private string _properyName;
private T _defaultValue;
private Settings _settings;
internal LanguageSpecificProperty(Settings settings, string propertyName, T defaultValue)
{
_properyName = propertyName;
_defaultValue = defaultValue;
}
public T this[string lang]
{
get
{
return _settings.Get<T>(_properyName, lang, _defaultValue);
}
set
{
_settings.Set<T>(_properyName, lang, value);
}
}
}
public class LanguageSpecificPropertyFactory
{
private Dictionary<string, object> _properties = new Dictionary<string, object>();
private Settings _settings;
public LanguageSpecificPropertyFactory(Settings settings)
{
_settings = settings;
}
internal LanguageSpecificProperty<T> GetLanguageProperty<T>(string propertyName, T defaultValue)
{
if (!_properties.ContainsKey(propertyName))
{
_properties.Add(propertyName, new LanguageSpecificProperty<T>(_settings, propertyName, defaultValue));
}
return (LanguageSpecificProperty<T>)_properties[propertyName];
}
}
}
Related
I define a DynamicObject.
I have created a list of DynamicObjects with the same structure and link them to a WPF GridView.
I allow editing of some of the properties via the grid.
As the DynamicObjects present the property data as objects, how can I enforce Type restrictions?
if the user types alphabet into a cell that I would like as an int how can I get the DynamicObject to refuse the input?
You could use a TryParse wherever you're taking the cell input:
int result;
if(int.TryParse(cellText, out result))
{
// Is an integer
}
else
{
}
bool and other value types also have a TryParse if you're taking those values as well.
See also:
Comparing Types in this question
The DynamicDictionary example in the docs for a more verbose implementation on adding and editing properties.
In the constructor of my DynamicObject, I pass in with the properties definition, a dictionary of the types.
I then override the TrySetMember method to convert the value from the string supplied by the grid into its required type.
The issue I now have is sending a error message back to the grid if the conversion fails.
Here is My DynamicObject definition:
public sealed class FwDynamicObject : DynamicObject
{
private readonly Dictionary<string, object> _properties;
private readonly Dictionary<string, Type> _propertyTypes;
public FwDynamicObject(Dictionary<string, object> properties, Dictionary<string, Type> propertyTypes = null)
{
_properties = properties;
_propertyTypes = propertyTypes;
}
public override IEnumerable<string> GetDynamicMemberNames()
{
return _properties.Keys;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_properties.ContainsKey(binder.Name))
{
result = _properties[binder.Name];
return true;
}
else
{
result = null;
return false;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (_properties.ContainsKey(binder.Name))
{
var t = GetMemberType(binder.Name);
if (t != null)
{
try
{
value = Convert.ChangeType(value, t);
}
catch(Exception e)
{
return false;
}
}
_properties[binder.Name] = value;
return true;
}
else
{
return false;
}
}
private Type GetMemberType(string name)
{
if (_propertyTypes.ContainsKey(name))
{
return _propertyTypes[name];
}
return null;
}
}
I have to rework some code and stumbled upon a few classes which define a huge amount of very similar properties.
They look something like this:
public _ReturnType _PropertyName
{
get
{
IMarkerInterface value = null;
if (Properties != null) Properties.TryGetValue(_string, out value);
return value as _ReturnType;
}
set { Properties[_string] = value; }
}
The only difference between them is the _ReturnType, the _string that is used in the dictionary Properties and obviously the _PropertyName.
I was wondering if there is a way to shorten the syntax?
If you see duplicate code, you extract a method. It would look something like this:
private T GetValueOrDefault<T>(string key)
{
IMarkerInterface value = null;
if (Properties != null) Properties.TryGetValue(key, out value);
return value as T;
}
Then change your getter:
get
{
return GetValueOrDefault<_ReturnType>("key");
}
But if this code is spread out over multiple classes, you'd have to define a base class containing the Properties property and the above GetValueOrDefault() method, albeit protected instead of private.
Alternatively, you'd define it as an extension method on whatever the type of Properties is:
public static T GetValueOrDefault<T>(this IDictionary<string, IMarkerInterface> properties, string key)
{
IMarkerInterface value = null;
if (properties != null) properties.TryGetValue(key, out value);
return value as T;
}
And call it as such:
get
{
return Properties.GetValueOrDefault<_ReturnType>("key");
}
But, as #Daniel comments, this smells like an ideal scenario for code generation, because without that you'd still have a couple of lines of (copy-pasted, error-prone) code.
There probably is a source somewhere for what these properties should be named, and you can use something like T4 templates to generate this code file from it.
Well, you could do this:
private IMarkerInterface getIMF(string str)
{
IMarkerInterface value = null;
Properties?.TryGetValue(_string, out value);
return value;
}
public _ReturnType _PropertyName
{
get { return getIMF(_string) as _ReturnType; }
set { Properties[_string] = value; }
}
If Properties implements IReadOnlyDictionary<string, object> (like a Dictionary<string, object> for instance), one thing you could do is add an extension method:
public static TValue TryGetValue<TValue>(
this IReadOnlyDictionary<string, object> properties,
string key)
where TValue : class
{
if ((properties != null) &&
properties.TryGetValue(key, out object value))
{
return value as TValue;
}
return null;
}
and then
public IMarkerInterface MarkerInterface
{
get => Properties.TryGetValue<IMarkerInterface>("MarkerInterface");
set { Properties["MarkerInterface"] = value; }
}
Link to Fiddle
I have a scenario where I need the properties in my class to map to a dictionary. Here is a code sample:
public string Foo
{
get
{
if (!PropertyBag.ContainsKey("Foo"))
{
return null;
}
return PropertyBag["Foo"];
}
set
{
PropertyBag["Foo"] = value;
}
}
I have to apply this pattern to multiple properties. Is there a way to use attributes to do that?
I know that PostSharp would work for this purpose, but I was hoping there is a way to do it without using it.
This feels like a code smell to me. It would be better to use regular POCOs and convert them to a Dictionary only when needed.
public class BlogPost
{
public string Title { get; set; }
public string Body { get; set; }
public int AuthorId { get; set; }
public Dictionary<string, object> ToDictionary()
{
return this.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.ToDictionary(prop => prop.Name, prop => prop.GetValue(this, null));
}
}
Inspiration: How to convert class into Dictionary?
And to be honest, a ToDictionary method on your POCO's seems like a code smell. It would be better to refactor your code so the conversion of POCOs to Dictionaries happens in its own layer, as a service maybe.
Edit: This Gist I found while searching google for "c# convert object to dictionary" could provide a more generalized solution, and probably more bullet proof than my cobbled together example:
Gist: https://gist.github.com/jarrettmeyer/798667
From the Gist:
public static class ObjectToDictionaryHelper
{
public static IDictionary<string, object> ToDictionary(this object source)
{
return source.ToDictionary<object>();
}
public static IDictionary<string, T> ToDictionary<T>(this object source)
{
if (source == null)
ThrowExceptionWhenSourceArgumentIsNull();
var dictionary = new Dictionary<string, T>();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
AddPropertyToDictionary<T>(property, source, dictionary);
return dictionary;
}
private static void AddPropertyToDictionary<T>(PropertyDescriptor property, object source, Dictionary<string, T> dictionary)
{
object value = property.GetValue(source);
if (IsOfType<T>(value))
dictionary.add(property.Name, (T)value);
}
private static bool IsOfType<T>(object value)
{
return value is T;
}
private static void ThrowExceptionWhenSourceArgumentIsNull()
{
throw new ArgumentNullException("source", "Unable to convert object to a dictionary. The source object is null.");
}
}
Credit: jerrettmeyer at GitHub
This should add a ToDictionary method to every object.
Edit: From the following comment
To give a bit of context, I am using Entity Framework and I have a class hierarchy that I would like to keep in one table while avoiding null columns everywhere.
Entity framework supports multiple table inheritance. That might be a better solution in your case.
You can write a GetValueOrDefault extension method and reduce the code a little.
public static class DictionaryExtensions
{
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey,TValue> self, TKey key)
{
TValue value;
self.TryGetValue(key,out value);
return value;
}
}
public string Foo
{
get
{
return PropertyBag.GetValueOrDefault("Foo");
}
set
{
PropertyBag["Foo"] = value;
}
}
You can eliminate the magic strings using expressions.
If you're using at least .NET 4.5 then you have the CallerMemberNameAttribute which you could use like this:
class SomeClass
{
public string Foo
{
get
{
return GetPropertyValue();
}
set
{
SetPropertyValue( value );
}
}
private string GetPropertyValue( [CallerMemberName] string name = null )
{
string value;
PropertyBag.TryGetValue( name, out value );
return value;
}
private void SetPropertyValue( string value, [CallerMemberName] string name = null )
{
PropertyBag[name] = value;
}
}
This will result in the compiler filling out the name of the member for you. If you're not (or otherwise can't) use .NET 4.5, another alternative would be to take advantage of expression trees as suggested in another answer.
class Test
{
Dictionary<string,object> _values = new Dictionary<string, object>();
public string Foo
{
get
{
var value = GetValue();
return value == null ? string.Empty : (string)value;
}
set
{
SetValue(value);
}
}
private object GetValue()
{
var stack = new StackTrace();
var key = GetGenericName(stack.GetFrame(1).GetMethod().Name);
if (_values.ContainsKey(key)) return _values[key];
return null;
}
private void SetValue(object value)
{
var stack = new StackTrace();
var key = GetGenericName(stack.GetFrame(1).GetMethod().Name);
_values[key] = value;
}
private string GetGenericName(string key)
{
return key.Split('_')[1];
}
}
I've been researching a bit about reflections in C # and would like to know if I use a dictionary with keys-values can create an object with the variable with the name of each key in the dictionary and their values, the key value of that dictionary.
I have a method that does the opposite, that extracts an object from a dictionary, this dictionary contains the keys and the class properties and their values, the value of the properties.
I wonder how to do this if possible.
Below is my method, which extracts a dictionary of an object:
protected Dictionary<String, String> getObjectProperty(object objeto)
{
Dictionary<String, String> dictionary = new Dictionary<String, String>();
Type type = objeto.GetType();
FieldInfo[] field = type.GetFields();
PropertyInfo[] myPropertyInfo = type.GetProperties();
String value = null;
foreach (var propertyInfo in myPropertyInfo)
{
if (propertyInfo.GetIndexParameters().Length == 0)
{
value = (string)propertyInfo.GetValue(objeto, null);
value = value == null ? null : value;
dictionary.Add(propertyInfo.Name.ToString(), value);
}
}
return dictionary;
}
If you've already got a dictionary, I'd avoid reflection and just use DynamicObject
For example:
public class DynamicDictionary : DynamicObject
{
private readonly Dictionary<string, object> dictionary;
public DynamicDictionary(Dictionary<string, object> dictionary)
{
this.dictionary = dictionary;
}
public override bool TryGetMember(
GetMemberBinder binder, out object result)
{
return dictionary.TryGetValue(binder.Name, out result);
}
public override bool TrySetMember(
SetMemberBinder binder, object value)
{
dictionary[binder.Name] = value;
return true;
}
}
Which can be used as follows:
dynamic x = new DynamicDictionary(
new Dictionary<string, object> {{"Name", "Peter"}});
Console.WriteLine(x.Name);
I am not sure if this is what you're looking for, but judging by your question, I think you want to
instantiate types at run time from the types located in a dictionary, which will be obtained by providing a key.
If that is so, then you can create the following class which will hold key-value pairs of strings which will be your keys, and Types which will represent your values which will be instantiated.
class DictionaryActivator
{
Dictionary<string, Type> Dictionary = new Dictionary<string, Type>();
public DictionaryActivator()
{
Dictionary.Add("MyCar", typeof(Car));
Dictionary.Add("MyHouse", typeof(House));
Dictionary.Add("MyFruit", typeof(Fruit));
Dictionary.Add("MyComputer", typeof(Computer));
}
public T GetInstance<T>(string type, params object[] parameters)
{
if (parameters.Count() == 0)
{
return (T)Activator.CreateInstance(Dictionary[type]);
}
else
{
return (T)Activator.CreateInstance(Dictionary[type], parameters.ToArray());
}
}
}
You can also create four test classes to test this setup.
class House
{
public int Number = 25;
}
class Car
{
public double Price = 50000;
}
class Fruit
{
public string Name = "Apple";
}
class Computer
{
public string Cpu { get; set; }
public string Gpu { get; set; }
public Computer(string cpu, string gpu)
{
Cpu = cpu;
Gpu = gpu;
}
}
Once this is done, you can run the following lines of code to get all the types from the dictionary, instantiate them and cast them to appropriate types. As you might notice, the last Computer example is showing you how to add multiple parameters (in this case two) to the newly created instance and return it as an instance of type object.
In the end you can cast it to the Computer type so you can check that the constructor parameters actually went to the corresponding properties.
class Program
{
static void Main()
{
var source = new DictionaryActivator();
Console.WriteLine(source.GetInstance<Car>("MyCar").Price);
Console.WriteLine(source.GetInstance<House>("MyHouse").Number);
Console.WriteLine(source.GetInstance<Fruit>("MyFruit").Name);
var computer = source.GetInstance<object>("MyComputer", "Fast CPU", "Fast GPU");
Console.WriteLine((computer as Computer).Cpu);
Console.WriteLine((computer as Computer).Gpu);
Console.Read();
}
}
Since ExpandoObject is a dictionary, you can use this extension function:
public static object With(this IDictionary<string, object> obj, IDictionary<string,object> additionalProperties)
{
foreach (var name in additionalProperties.Keys)
obj[name] = additionalProperties[name];
return obj;
}
Usage:
var dynamicObj = new System.Dynamic.ExpandoObject().With(myDictionary);
So I have the following snippet of code:
private Nullable<decimal> _excessWages;
public decimal ExcessWages
{
get
{
return _excessWages ?? CalculateExcessWages();
}
set
{
if (value != CalculateExcessWages())
_excessWages = value;
else
_excessWages = null;
}
}
So basically the behavior I'm trying to implement is if a field is left blank or is assigned a value equal the calculated one use the calculated value, otherwise store the assigned value.
I have a lot of fields that need to support overriding like this. Is this the best way to accomplish this? If not what would you suggest?
I worked on this a bit based mostly on Vlad's suggestion. Turns out you can use a single generic class to abstract this. Here is the end result:
public class Overridable<T>
{
private Func<T> _calculate;
private readonly Func<T, T, bool> _compare;
protected T _t;
public Overridable(Func<T> calculate, Func<T, T, bool> compare)
{
_calculate = calculate;
_compare = compare;
}
public T Value
{
get { return _compare(_t, default(T)) ? _calculate() : _t; }
set { _t = _compare(value, _calculate()) ? default(T) : value; }
}
}
You need to pass in a compare delegate because the type isn't known until you set it in a subclass. So a simple == isn't going to cut it. I went the easy route and used a Func delegate but this could be replaced with a normal delegate if it had to be adapted for .NET 2.0 for some reason.
You'll notice I'm using default(T) instead of null. This works because the default value for a Nullable<T> is null (or more precisely, undefined but it works out to be the same).
This doesn't prevent you from trying to declare an Overridable<T> for a non-nullable type. What you'd wind up with won't through run time errors but it isn't as useful. Trying to set a Overridable<decimal>.Value to null will get you a compiler error. While setting it to default(decimal) will cause it to revert to calculating the value.
I went this route because the properties from this the class I'm using this in needs to populate a serializable object thats eventually transmitted as xml. The schema for the xml includes numeric fields defined as a mixture of integers, decimals and strings.
You then use the Overriddable class like so:
private Overridable<decimal?> _excessWages =
new Overridable<decimal?>(CalculateExcessWages, (x,y) => x == y);
public virtual decimal? ExcessWages
{
get
{
return _excessWages.Value;
}
set
{
_excessWages.Value = value;
}
}
The only problem I ran into with this was that CalculateExcessWages is a non-static method so it can't be used in a field initializer. Since all the properties in my class are non-static I had to initialize all the backing fields in the constructor.
You can make a class wrapper for this.
class OverridableValue<T>
{
public OverridableValue<T>(Func<T> calculator)
{
_calculator = calculator;
}
private Nullable<T> _t;
private Func<T> _calculator;
public T Get()
{
return return _t ?? _calculator();
}
public void Set(T value)
{
_t = (value != _calculator()) ? value : null;
}
}
It's not so syntactically sweet, but at least saves some keystrokes.
Now you can use it like this:
class Foo
{
OverridableValue<decimal> _excessWages =
new OverridableValue<decimal>(CalculateExcessWages);
public decimal ExcessWages
{
get { return _excessWages.Get(); }
set { _excessWages.Set(value); }
}
...
}
The advantage is that the whole logic is hidden at the class.
You could do this by defining a handy set/get helper method
private static T GetUtil<T>(ref Nullable<T> value, Func<T> calc) {
return value ?? calc();
}
private static void SetUtil<T>(ref Nullable<T> value, T newValue, Func<T> calc) {
if ( newValue != calc() ) {
value = newValue
} else {
value = null;
}
}
private Nullable<decimal> _excessWages;
public decimal ExcessWages
{
get { return GetUtil(ref _excessWages, CalculateExcessWages); }
set { SetUtil(ref _excessWages, value CalculateExcessWages); }
}
That looks reasonable to my eyes. The only change I might make is to cache CalculateExcessWages(), if it is expensive to do, and ok to cache:
private Nullable<decimal> _excessWages;
private Nullable<decimal> _excessWagesCalculated;
public virtual decimal ExcessWages
{
get
{
if (_excessWagesCalculated == null)
_excessWagesCalculated = CalculateExcessWages();
return _excessWages ?? _excessWagesCalculated;
}
set
{
if (_excessWagesCalculated == null)
_excessWagesCalculated = CalculateExcessWages();
if (value != _excessWagesCalculated)
_excessWages = value;
else
_excessWages = null;
}
}
But, this is more code than yours, and I think you are looking to simplify.