I have a class which stores value.
public class Entry<T>
{
private T _value;
public Entry() { }
public Entry(T value)
{
_value = value;
}
public T Value
{
get { return _value; }
set { _value = value; }
}
// overload set operator.
public static implicit operator Entry<T>(T value)
{
return new Entry<T>(value);
}
}
To utilize this class:
public class Exam
{
public Exam()
{
ID = new Entry<int>();
Result = new Entry<int>();
// notice here I can assign T type value, because I overload set operator.
ID = 1;
Result = "Good Result.";
// this will throw error, how to overload the get operator here?
int tempID = ID;
string tempResult = Result;
// else I will need to write longer code like this.
int tempID = ID.Value;
string tempResult = Result.Value;
}
public Entry<int> ID { get; set; }
public Entry<string> Result { get; set; }
}
I'm able to overload the set operator which I can straightaway do "ID = 1".
But when I do "int tempID = ID;", it will throw error.
How to overload the get operator so I can do "int tempID = ID;" instead of "int tempID = ID.Value;"?
Simple, add another implicit operator but for the other direction!
public class Entry<T>
{
private T _value;
public Entry() { }
public Entry(T value)
{
_value = value;
}
public T Value
{
get { return _value; }
set { _value = value; }
}
public static implicit operator Entry<T>(T value)
{
return new Entry<T>(value);
}
public static implicit operator T(Entry<T> entry)
{
return entry.Value;
}
}
And usage is a breeze:
void Main()
{
Entry<int> intEntry = 10;
int val = intEntry;
}
Related
Lets say you have a complex type:
public class Identity<TEntity> : IEquatable<Identity<TEntity>>
{
public Identity(Guid value)
{
Value = value;
}
public Guid Value { get; }
public static implicit operator Guid(Identity<TEntity> identity)
{
return identity.Value;
}
public static explicit operator Identity<TEntity>(Guid value)
{
return new Identity<TEntity>(value);
}
}
How to configure a type using this complex type as Id, e.g.
public class MyEntity
{
public Identity<TEntity> Id { get; }
}
within a type configuration for ef core?
For example a type configuration like:
public class MyEntityTypeConfiguration : IEntityTypeConfiguration<MyEntity>
{
public void Configure(EntityTypeBuilder<MyEntity> builder)
{
var converter = new ValueConverter<Identity<MyEntity>, Guid>(
v => v.Value,
v => new Identity<MyEntity>(v));
builder.HasKey(e => e.Id);
builder.Property(e => e.Id)
.ValueGeneratedOnAdd()
.HasConversion(converter);
}
}
will produce an empty Guid (no values generated).
You have a constructor which set the Value. In order to get a value you need to set a value like below.
Identity<Gibra> identity = new Identity<Gibra>(Guid.NewGuid());
Or you have a empty constructor
public class Identity<TEntity> : IEquatable<Identity<TEntity>>
{
Guid _value = Guid.NewGuid();
public Identity(Guid value)
{
Value = value;
}
public Identity()
{
}
public Guid Value { get { return _value; } set { _value = value; } }
public bool Equals(Identity<TEntity> other)
{
throw new NotImplementedException();
}
public static implicit operator Guid(Identity<TEntity> identity)
{
return identity.Value;
}
public static explicit operator Identity<TEntity>(Guid value)
{
return new Identity<TEntity>(value);
}
}
So that you can use like this
Identity<Gibra> identity = new Identity<Gibra>();
Is there a way to do something like "string.Compare()", but for generic types. I want to check the range of some property values.
Here is what I am doing as a work around, but it is pretty ugly:
public class SomeClass<T>
{
public T MinValue { get; set; }
public T MaxValue { get; set; }
private T _value;
public T Value
{
get { return _value; }
set
{
_value = value;
// Restrict range to Min/Max
if (Comparer<T>.Default.Compare(MaxValue, value) < 0)
_value = MaxValue;
if (Comparer<T>.Default.Compare(MinValue, value) > 0)
_value = MinValue;
}
}
}
This code demonstates what I was talking about in my comment. Of course you will have to modify it to fit with your precise paradigm, of using it in a comparer, but this should be clear enough...
public class Program
{
public static void Main(string[] args)
{
System.Console.WriteLine("Hello World!");
TestObject testObject = new TestObject(15);
TestObject testObject2 = new TestObject(9);
TestObject testObject3 = new TestObject(31);
System.Console.ReadLine();
}
}
public class TestObject
{
[ValidateIntMin(Min = 10)]
[ValidateIntMax(30)]
public int SomeInt { get; set; }
public TestObject(int value)
{
SomeInt = value;
if (!Validator.Validate(this))
{
System.Console.WriteLine("Invalid Value assigned: " + value);
}
else
{
System.Console.WriteLine("" + SomeInt + " was a valid value");
}
}
}
public class ValidateIntMax : Attribute
{
public int Max { get; set; }
public ValidateIntMax(int MaxValue)
{
Max = MaxValue;
}
}
public class ValidateIntMin: Attribute
{
public int Min { get; set; }
}
public static class Validator
{
public static bool Validate<T>(T input) {
var attrType = typeof(T);
var properties = attrType.GetProperties();
bool isValid = true;
foreach (PropertyInfo propertyInfo in properties)
{
var customerMaxValueInt = propertyInfo.GetCustomAttributes(typeof(ValidateIntMax), false).FirstOrDefault();
var customerMinValueInt = propertyInfo.GetCustomAttributes(typeof(ValidateIntMin), false).FirstOrDefault();
if (customerMaxValueInt != null)
{
if (propertyInfo.PropertyType == typeof(int))
{
var currentPropertyInfoBeingTested = (int)propertyInfo.GetValue(input);
var currentMaxValueToVerifyAgainst = ((ValidateIntMax)customerMaxValueInt).Max;
if (currentPropertyInfoBeingTested > currentMaxValueToVerifyAgainst)
{
isValid = false;
}
}
}
if (customerMinValueInt != null)
{
if (propertyInfo.PropertyType == typeof(int))
{
var currentPropertyInfoBeingTested = (int)propertyInfo.GetValue(input);
var currentMaxValueToVerifyAgainst = ((ValidateIntMin)customerMinValueInt).Min;
if (currentPropertyInfoBeingTested < currentMaxValueToVerifyAgainst)
{
isValid = false;
}
}
}
}
return isValid;
}
}
Should give the output:
Hello World!
15 was a valid value
Invalid Value assigned: 9
Invalid Value assigned: 31
Of course you can add validation for different types, etc.
This is just to show a totally custom way of setting up your attributes.
I recommend you read up on the ValidationAttribute however, to see if you can't use the implemented functionality.
But this is just a PoC piece.
Is it possible to have an enum based custom attribute that could be set atop some class property in C#.Net?
Example: I am trying to do the following:
[AutoUpdateEnumParam(new AutoUpdateParamOption[]
{ new AutoUpdateParamOption("Offline", 0),
new AutoUpdateParamOption("Online", 1),
new AutoUpdateParamOption("Deactivated", 2),
new AutoUpdateParamOption("Reset", 3),
new AutoUpdateParamOption("Removed", 4) })]
public int Status
{
get;
set;
}
When I compile the project, it gives me following error:
An attribute argument must be a constant expression, typeof expression
or array creation expression of an attribute parameter type
[UPDATE]
Somebody asked me, how I have defined my AutoUpdateEnumParam class. Here it is:
[AttributeUsage(AttributeTargets.Property)]
public class AutoUpdateEnumParam : Attribute
{
AutoUpdateParamOption[] _paramEnum;
public AutoUpdateParamOption[] Options
{
get
{
return _paramEnum;
}
}
public AutoUpdateEnumParam(AutoUpdateParamOption[] paramEnum)
{
this._paramEnum = paramEnum;
}
}
public class AutoUpdateParamOption
{
private string _text = string.Empty;
private object _value = null;
private string _type = "string";
public string Text
{
get
{
return _text;
}
}
public object Value
{
get
{
return _value;
}
}
public string ValueType
{
get
{
return _type;
}
}
public AutoUpdateParamOption(string text, int value)
{
this._text = text;
this._value = value;
this._type = "int";
}
public AutoUpdateParamOption(string text, double value)
{
this._text = text;
this._value = value;
this._type = "double";
}
public AutoUpdateParamOption(string text, string value)
{
this._text = text;
this._value = value;
this._type = "string";
}
public AutoUpdateParamOption(string text, bool value)
{
this._text = text;
this._value = value;
this._type = "boolean";
}
}
Newtonsoft.json does not seem to be able to convert int to my nInt struct. I'm not sure why. The purpose of my struct is to allow int to be set to null, but not actually be null and instead default to 0.
Here is my code:
nInt:
/// <summary>
/// Non-nullable int. Defaults to 0.
/// </summary>
public struct nInt
{
public nInt(int? value)
: this()
{
Value = value ?? 0;
}
private void deNullify()
{
Value = Value ?? 0;
}
public int? Value
{
get;
private set;
}
public static implicit operator nInt(int value)
{
return new nInt(value);
}
public static implicit operator nInt(int? value)
{
return new nInt(value);
}
public static implicit operator int?(nInt value)
{
return value.Value ?? 0;
}
public static implicit operator int(nInt value)
{
return value.Value ?? 0;
}
public override bool Equals(object other)
{
deNullify();
return Value.Equals(other);
}
public override int GetHashCode()
{
deNullify();
return Value.GetHashCode();
}
public Type GetType()
{
return typeof(int?);
}
public int GetValueOrDefault(int defaultValue)
{
deNullify();
return Value.GetValueOrDefault(defaultValue);
}
public bool HasValue
{
get { deNullify(); return Value.HasValue; }
}
public override string ToString()
{
deNullify();
return Value.ToString();
}
}
nInt usage:
public class TotalCountObject
{
public nInt totalCount { get; set; }
}
TotalCountObject tco = JsonConvert.DeserializeObject<TotalCountObject>(jsonString, jsonSerializerSettings);
// here is where i get Error converting value 333 to type 'nInt'.
You don't need to create your own type to do this. You can use the NullValueHandling options in JSON.NET to ignore nulls for non-nullable types. For example:
public class TotalCountObject
{
[JsonProperty(NullValueHandling = NullValueHanding.Ignore)]
public int totalCount { get; set; }
}
Since the default value of int is 0, when this property is ignored, its value will be zero.
You can also set this property in JsonSerializerSettings:
var settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
TotalCountObject tco = JsonConvert.DeserializeObject<TotalCountObject>(
jsonString, jsonSerializerSettings);
Although that may not be a route you want to take if you don't want the NullValueHandling to apply to all properties.
How can I make a class like this:
public class Foo
{
private string m_value;
public string Value { get { return m_value; } set { m_value = value; } }
public Foo()
{
m_value = "";
}
}
be directly comparable with a string without needing to access it's .Value property so that I can do:
Foo m_foo = new Foo();
m_foo = "someString";
if(m_foo == "someString")
{
Console.Writeline("It Worked!");
}
I'm not sure if this is even possible.
You can overload the == operator (the compiler also requires you overload '!=', 'Equals', and 'GetHashCode')
public class Foo
{
private string m_value;
public string Value { get { return m_value; } set { m_value = value; } }
public Foo()
{
m_value = "";
}
public override bool Equals(object obj)
{
return this.Value == obj.ToString();
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public static bool operator ==(Foo a, string b)
{
return a.Value == b;
}
public static bool operator !=(Foo a, string b)
{
return a.Value != b;
}
}
I'm not sure if all of that effort is worth it though, when you could just write:
if(m_foo.Value == "someString")