NHibernate - Conversion failed when converting datetime from binary/varbinary string - c#

Note, this is some ancient NHibernate installation! I have the following NHibernate class:
[Serializable]
[Class(Table = "SomeEvents")]
public class SomeEvent
{
[Property(Column="processDate")]
public DateTime? ProcessDate { get; set; }
}
When trying to update some events like:
using (ISession session = FDK_Hibernate_Manager.OpenSession())
{
IQuery query = session.CreateQuery(string.Format("FROM {0} e WHERE e.ContractId = :cid", typeof(ContractLeverconditiesEvent)));
query.SetInt32("cid", contractId);
foreach(var evnt in query.List().Cast<SomeEvent>())
{
evnt.ProcessDate = DateTime.Now;
session.SaveOrUpdate(evnt);
}
session.Flush();
}
I receive the following exception:
Conversion failed when converting datetime from binary/varbinary string.
So I basically guess that NHibernate doesn't understand my DateTime? yet. My NHibernate install doesn't have any fancy Nullables.NHibernate.NullableDateTimeType. So anyone has a clue to solve this ancient NHibernate issue?

I ended up with this (although it can require some work in error-checking and such :-))
Implement it using [Property(Column = "processDate", TypeType = typeof(NullableDateTime))]
class NullableDateTime : IUserType
{
#region IUserType Members
public new bool Equals(object obj, object obj2)
{
return false;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public object DeepCopy(object value)
{
return value;
}
public bool IsMutable
{
get { return true; }
}
public object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner)
{
object o = rs[names[0]];
if (o == DBNull.Value) return new Nullable<DateTime>();
else
return new Nullable<DateTime>(((System.Data.SqlTypes.SqlDateTime)o).Value);
}
public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index)
{
System.Data.Common.DbParameter parameter = (System.Data.Common.DbParameter)cmd.Parameters[index];
if (value == null)
{
parameter.Value = DBNull.Value;
return;
}
else
{
parameter.Value = new System.Data.SqlTypes.SqlDateTime((DateTime)value);
}
}
public Type ReturnedType
{
get { return this.GetType(); }
}
public NHibernate.SqlTypes.SqlType[] SqlTypes
{
get { return new NHibernate.SqlTypes.SqlType[] { new SqlDateTimeType() }; }
}
#endregion
}
public class SqlDateTimeType : NHibernate.SqlTypes.SqlType
{
public SqlDateTimeType() : base(System.Data.DbType.DateTime)
{
}
}

Unfortunately, you'll probably have to use a proxy value (magic number) for the null date. 1/1/1900 is a common choice. If you can map a private member (I don't use attributes), you could control the value through the public property:
public class SomeEvent
{
private DateTime _processDate; // map this
public SomeEvent()
{
_processDate = new DateTime(1900, 1, 1);
}
public DateTime? ProcessDate
{
get
{
if (_processDate == new DateTime(1900, 1, 1))
{
return null;
}
return _processDate;
}
set
{
_processDate = value ?? new DateTime(1900, 1, 1);
}
}
}

Related

set multiple return value for method declaration

I have a function as below:
public var UpdateMapFetcher(int stationID, int typeID)
I need this function to return either string or int.
My return value is set as below
if (finaloutput == "System.String")
{
// param1[i] = Convert.ChangeType(typeID_New.ToString(), typeof(string));
returnvalue = returnvalue.ToString();
return returnvalue;
}
else if (finaloutput == "System.Int32")
{
int a=0;
a = Convert.ToInt32(returnvalue);
return a;
}
How to have either one data type as return value in dynamic environment.
My intuition tells me, that you are trying to convert string value to some type. In that case you can use:
public T UpdateMapFetcher<T>(int stationID)
{
//var someValue = "23";
return (T)Convert.ChangeType(someValue, typeof(T));
}
//then
var typed = UpdateMapFetcher<int>(6);
In case you don't know T, you can use mapping (0-int, 1-string, etc.):
public object UpdateMapFetcher(int stationID, int type)
{
var typeMap = new []{ typeof(int), typeof(string)};
//var someValue = "23";
return Convert.ChangeType(someValue, typeMap[type]);
}
//then
var untyped = UpdateMapFetcher(6, 0/*0 is int*/);
if (untyped.GetType() == typeof(int))
{ /*is int*/
}
Another solution is to use implicit conversions:
public class StringOrInt
{
private object value;
public ValueType Type { get; set; }
public static implicit operator StringOrInt(string value)
{
return new StringOrInt()
{
value = value,
Type = ValueType.String
};
}
public static implicit operator StringOrInt(int value)
{
return new StringOrInt()
{
value = value,
Type = ValueType.Int
};
}
public static implicit operator int(StringOrInt obj)
{
return (int)obj.value;
}
public static implicit operator string(StringOrInt obj)
{
return (string)obj.value;
}
}
public enum ValueType
{
String,
Int
}
And then (simplified):
public static StringOrInt UpdateMapFetcher(int stationID, int typeID)
{
if (typeID == 0)
return "Text";
return 23;
}
private static void Main(string[] args)
{
var result = UpdateMapFetcher(1, 1);
if (result.Type == ValueType.String) { }//can check before
int integer = result;//compiles, valid
string text = result;//compiles, fail at runtime, invalid cast
}
you can return an object. You'd have to subsequently check for types in your consuming method. I assume that won't be a problem in your usecase.
your method signature is therefore:
public object UpdateMapFetcher(int stationID, int typeID)
You also have the option of using the out keyword, which permits you to accept both into variables and check after the function has been called.
public void UpdateMapFetcher(int stationID, int typeID, out int intValue, out string strValue)
// or int return val and out string value
public int UpdateMapFetcher(int stationID, int typeID, out string strValue)
With the use appearing something like this:
int intVal;
string strVal;
UpdateMapFetcher(stationID, typeID, out intVal, out strVal);
if (strVal != null)
{
doSomethingWithString(strVal);
}
else
{
doSomethingWithInt(intVal);
}
Frankly, I would just return a Tuple, with string being non-null indicating string value to use, and null as indicator for int return
public Tuple<string, int> UpdateMapFetcher(int stationID, int typeID) {
if (finaloutput == "System.String")
{
// param1[i] = Convert.ChangeType(typeID_New.ToString(), typeof(string));
returnvalue = returnvalue.ToString();
return new Tuple<string, int>(returnvalue, 0);
}
else if (finaloutput == "System.Int32")
{
int a=0;
a = Convert.ToInt32(returnvalue);
return new Tuple<string, int>(null, a);
}
}
On consumer side
var rc = UpdateMapFetcher( .... );
if (rc.Item1 != null) {
// code to use string value
} else {
// code to use int value
}
I would choose to return an object of new class which might look like this:
class Result {
public string StringValue { get; }
public string Int32Value { get; }
public bool IsString { get; }
public bool IsInt32 { get; }
public Result(string value) {
StringValue = value;
IsString = true;
}
public Result(int value) {
Int32Value = value;
IsInt32 = true;
}
}
This way you can check which Type is it by using Isxxx property. You can also enhance this with validation in value geters. F. e., for string it might look like this:
public string StringValue {
get {
if (IsString)
return m_stringValue;
throw new InvalidOperationException("Value is not a string.");
}
}
You can't really do exactly that, but there are several ways to do more or less what you want. You'd probably be better off change the design a little though.
Two ideas:
Either change your code to use two different methods, and call each of them as needed instead.
..Or return an object, which you can cast however you like..
..Or, use a generic method with TypeDescriptor, like the following.
Note that we here convert the value to string first even if it was an int, since we can then use a common method ConvertFromString() to convert it to whatever type T was.
public T UpdateMapFetcher<T>(int stationID, int typeID) {
// To allow parsing to the generic type T:
var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));
if(converter != null)
{
return (T)converter.ConvertFromString(returnvalue.ToString());
}
else
{
return default(T);
}
}
Usage:
var result = MyExtensions.UpdateMapFetcher<string>(1, 2);
or:
var result = MyExtensions.UpdateMapFetcher<int>(1, 2);
You can return Object and cast to type which you want.
public Object UpdateMapFetcher(int stationID, int typeID)
if (finaloutput == "System.String")
{
// param1[i] = Convert.ChangeType(typeID_New.ToString(), typeof(string));
returnvalue = returnvalue.ToString();
return returnvalue;
}
else if (finaloutput == "System.Int32")
{
int a=0;
a = Convert.ToInt32(returnvalue);
return a;
}
A type that can contain either one type or another is usually called (unsurprisingly) Either. It is a special case of a sum type, basically a discriminated union, tagged union, or disjoint union with exactly two cases (instead of an arbitrary number).
Unfortunately, there does not exist an implementation of an Either type in the standard libraries, but there are plenty of implementations to be found on Google, GitHub, and elsewhere … and porting one of the existing implementations from e.g. Haskell or Scala isn't that hard, either.
It looks a bit like this (forgive my code, I don't actually know C♯ that well):
using System;
abstract class Either<A, B>
{
public abstract bool IsLeft { get; }
public abstract bool IsRight { get; }
public abstract A Left { get; }
public abstract B Right { get; }
public abstract A LeftOrDefault { get; }
public abstract B RightOrDefault { get; }
public abstract void ForEach(Action<A> action);
public abstract void ForEach(Action<B> action);
public abstract void ForEach(Action<A> leftAction, Action<B> rightAction);
private sealed class L : Either<A, B>
{
private A Value { get; }
public override bool IsLeft => true;
public override bool IsRight => false;
public override A Left => Value;
public override B Right { get { throw new InvalidOperationException(); } }
public override A LeftOrDefault => Value;
public override B RightOrDefault => default(B);
public override void ForEach(Action<A> action) => action(Value);
public override void ForEach(Action<B> action) {}
public override void ForEach(Action<A> leftAction, Action<B> rightAction) => leftAction(Value);
internal L(A value) { Value = value; }
}
private sealed class R : Either<A, B>
{
private B Value { get; }
public override bool IsLeft => false;
public override bool IsRight => true;
public override A Left { get { throw new InvalidOperationException(); } }
public override B Right => Value;
public override A LeftOrDefault => default(A);
public override B RightOrDefault => Value;
public override void ForEach(Action<A> action) {}
public override void ForEach(Action<B> action) => action(Value);
public override void ForEach(Action<A> leftAction, Action<B> rightAction) => rightAction(Value);
internal R(B value) { Value = value; }
}
public static Either<A, B> MakeLeft(A value) => new L(value);
public static Either<A, B> MakeRight(B value) => new R(value);
}
And you'd use it like this:
static class Program
{
public static void Main()
{
var input = Console.ReadLine();
int intResult;
var result = int.TryParse(input, out intResult) ? Either<int, string>.MakeLeft(intResult) : Either<int, string>.MakeRight(input);
result.ForEach(r => Console.WriteLine("You passed me the integer one less than " + ++r), r => Console.WriteLine(r));
}
}

Generic ITypedList bound to a WinForms DataGridView: all rows show first item

I have a list of items which contain a dynamic property.
The goal is to have classes with defined properties, but also allow setting new properties to its instances on the fly. One sample is the 'MyDynamicObject' class in the code below.
The list (an instance of 'DynamicITypedList' in the code below) is then bound to a DataGridView, which will show and bind every property of the list items to a column.
The problem I face is: as soon as I make the 'DynamicITypedList' class implement 'ITypedList', all the rows in the DataGridView show the properties of the first item in the list !If I don't make the list class implement 'ITypedList' (comment out 'ITypedList' at the very end of the code below), the dynamically added properties values are not shown (because the specific GetItemProperties() is not called), but all rows show up in the DataGridView...
Can you please drive me towards a solution ?
Here is the calling code, ready to run in a WinForm containing one "datagridView1" control:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace Tests
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void buttonITypedList_Click(object sender, EventArgs e)
{
MyDynamicObject myDynamicObject1 = new MyDynamicObject();
myDynamicObject1.Id = 1;
myDynamicObject1.AsDynamic.NewProperty = "NEWPROP1";
MyDynamicObject myDynamicObject2 = new MyDynamicObject();
myDynamicObject2.Id = 2;
DynamicITypedList<MyDynamicObject> myDynamicObjectDynamicITypedList = new DynamicITypedList<MyDynamicObject>();
myDynamicObjectDynamicITypedList.Add(myDynamicObject1);
myDynamicObjectDynamicITypedList.Add(myDynamicObject2);
dataGridView1.AutoGenerateColumns = false;
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = myDynamicObjectDynamicITypedList;
bindingSource.AllowNew = true;
dataGridView1.DataSource = bindingSource;
foreach (KeyValuePair<string, object> property in myDynamicObject1.Data.Properties)
{
DataGridViewTextBoxColumn dynamicPropertyColumn = new DataGridViewTextBoxColumn();
dynamicPropertyColumn.DataPropertyName = property.Key;
dynamicPropertyColumn.HeaderText = property.Key;
dynamicPropertyColumn.Name = property.Key;
dataGridView1.Columns.Add(dynamicPropertyColumn);
}
}
}
}
Below are the classes:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
using System.Reflection;
namespace Tests
{
public interface IMyDynamic
{
MyDynamic Data { get; set; }
IEnumerable<string> GetDynamicMemberNames();
}
public class MyDynamic : DynamicObject, IDynamicMetaObjectProvider
{
object Instance { get; set; }
Type InstanceType { get; set; }
Dictionary<string, MemberInfo> MemberInfos { get; set; }
PropertyInfo[] instancePropertyInfo;
PropertyInfo[] InstancePropertyInfo
{
get
{
if (instancePropertyInfo == null && Instance != null)
instancePropertyInfo = Instance.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
return instancePropertyInfo;
}
}
public MyDynamic()
{
Initialize(this);
}
public MyDynamic(object instance)
{
Initialize(instance);
}
public IEnumerable<KeyValuePair<string, object>> GetProperties(bool includeInstanceProperties = false)
{
if (includeInstanceProperties && Instance != null)
{
foreach (var prop in this.InstancePropertyInfo)
yield return new KeyValuePair<string, object>(prop.Name, prop.GetValue(Instance, null));
}
foreach (var key in this.Properties.Keys)
yield return new KeyValuePair<string, object>(key, this.Properties[key]);
}
public override IEnumerable<string> GetDynamicMemberNames()
{
foreach (var prop in GetProperties(true))
yield return prop.Key;
}
public Dictionary<string, object> Properties { get; private set; }
public object this[string key]
{
get
{
try
{
//Try to get from properties collection first
return Properties[key];
}
catch (KeyNotFoundException)
{
//Try reflection on instanceType
object result = null;
if (GetProperty(Instance, key, out result))
return result;
//Nope doesn't exist
//throw; //Preserve the stack trace
return null;
}
}
set
{
if (Properties.ContainsKey(key))
{
Properties[key] = value;
return;
}
//Check instance for existance of type first
var miArray = InstanceType.GetMember(key, BindingFlags.Public | BindingFlags.GetProperty);
if (miArray != null && miArray.Length > 0)
SetProperty(Instance, key, value);
else
Properties[key] = value;
}
}
protected virtual void Initialize(object instance)
{
Instance = instance;
if (instance != null)
InstanceType = instance.GetType();
Properties = new Dictionary<string, object>();
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = null;
//First check the Properties collection for member
if (Properties.Keys.Contains(binder.Name))
{
result = Properties[binder.Name];
return true;
}
//Next check for Public properties via Reflection
if (Instance != null)
{
try
{
return GetProperty(Instance, binder.Name, out result);
}
catch { }
}
//Failed to retrieve a property
result = null;
return false;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
//First check to see if there's a native property to set
if (Instance != null)
{
try
{
if (SetProperty(Instance, binder.Name, value))
return true;
}
catch { }
}
//No match - set or add to dictionary
Properties[binder.Name] = value;
return true;
}
protected bool GetProperty(object instance, string name, out object result)
{
if (instance == null)
instance = this;
if (MemberInfos == null)
{
MemberInfos = new Dictionary<string, MemberInfo>();
MemberInfo[] memberInfos = InstanceType.GetMember(name, BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.Instance);
foreach (MemberInfo instanceMemberInfo in InstanceType.GetMembers())
MemberInfos.Add(instanceMemberInfo.Name, instanceMemberInfo);
}
result = null;
MemberInfo propertyMemberInfo;
if (!MemberInfos.TryGetValue(name, out propertyMemberInfo))
return false;
if (propertyMemberInfo.MemberType == MemberTypes.Property)
{
result = ((PropertyInfo)propertyMemberInfo).GetValue(instance, null);
return true;
}
return false;
}
protected bool SetProperty(object instance, string name, object value)
{
if (instance == null)
instance = this;
if (MemberInfos == null)
{
MemberInfos = new Dictionary<string, MemberInfo>();
MemberInfo[] memberInfos = InstanceType.GetMember(name, BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.Instance);
foreach (MemberInfo instanceMemberInfo in InstanceType.GetMembers())
MemberInfos.Add(instanceMemberInfo.Name, instanceMemberInfo);
}
MemberInfo propertyMemberInfo;
if (!MemberInfos.TryGetValue(name, out propertyMemberInfo))
return false;
if (propertyMemberInfo.MemberType == MemberTypes.Property)
{
((PropertyInfo)propertyMemberInfo).SetValue(Instance, value, null);
return true;
}
return false;
}
}
public /*abstract*/ class MyDynamicObject : MyDynamic, IMyDynamic
{
public MyDynamic Data
{
get { return data; }
set { data = dynamicData = value; }
}
public dynamic AsDynamic
{
get { return dynamicData; }
}
public Int64 Id { get { return AsDynamic.Id; } set { AsDynamic.Id = value; } }
MyDynamic data;
dynamic dynamicData;
public MyDynamicObject() : this(new MyDynamic())
{ }
public MyDynamicObject(MyDynamic data)
{
Data = data;
TypeDescriptor.AddProvider(new MyDynamicTypeDescriptionProvider(), this); //Data);
}
}
public class IMyDynamicTypeDescriptor : ICustomTypeDescriptor
{
private readonly IMyDynamic m_Instance;
public IMyDynamicTypeDescriptor(object instance)
{
if (instance is MyDynamicObject)
m_Instance = (MyDynamicObject)instance;
else if (instance is IMyDynamic)
m_Instance = (IMyDynamic)instance;
}
public string GetComponentName()
{
return TypeDescriptor.GetComponentName(this, true);
}
public EventDescriptor GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(this, true);
}
public string GetClassName()
{
return TypeDescriptor.GetClassName(this, true);
}
public EventDescriptorCollection GetEvents(Attribute[] attributes)
{
return TypeDescriptor.GetEvents(this, attributes, true);
}
EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
{
return TypeDescriptor.GetEvents(this, true);
}
public TypeConverter GetConverter()
{
return TypeDescriptor.GetConverter(this, true);
}
public object GetPropertyOwner(PropertyDescriptor pd)
{
return m_Instance;
}
public AttributeCollection GetAttributes()
{
return TypeDescriptor.GetAttributes(this, true);
}
public object GetEditor(Type editorBaseType)
{
return TypeDescriptor.GetEditor(this, editorBaseType, true);
}
public PropertyDescriptor GetDefaultProperty()
{
return null;
}
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
{
return ((ICustomTypeDescriptor)this).GetProperties(new Attribute[0]);
}
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
return new PropertyDescriptorCollection(
m_Instance.Data.Properties.Keys
.Select(x => new MyDynamicPropertyDescriptor(m_Instance, x))
.ToArray<PropertyDescriptor>());
}
}
public class MyDynamicPropertyDescriptor : PropertyDescriptor
{
private readonly IMyDynamic m_Instance;
private readonly string m_Name;
public MyDynamicPropertyDescriptor(IMyDynamic instance, string name)
: base(name, null)
{
m_Instance = instance;
m_Name = name;
}
public override Type PropertyType
{
get
{
if (m_Instance.Data[m_Name] != null)
return m_Instance.Data[m_Name].GetType();
else
{
//...
return typeof(string);
}
}
}
public override void SetValue(object component, object value)
{
m_Instance.Data[m_Name] = value;
}
public override object GetValue(object component)
{
return m_Instance.Data[m_Name];
}
public override bool IsReadOnly
{
get { return false; }
}
public override Type ComponentType
{
get { return null; }
}
public override bool CanResetValue(object component)
{
return false;
}
public override void ResetValue(object component)
{ }
public override bool ShouldSerializeValue(object component)
{
return false;
}
public override string Category
{
get { return string.Empty; }
}
public override string Description
{
get { return string.Empty; }
}
}
public class MyDynamicTypeDescriptionProvider : TypeDescriptionProvider
{
private static readonly TypeDescriptionProvider m_Default = TypeDescriptor.GetProvider(typeof(ExpandoObject));
public MyDynamicTypeDescriptionProvider() : base(m_Default)
{ }
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
var defaultDescriptor = base.GetTypeDescriptor(objectType, instance);
return (instance == null ? defaultDescriptor : new IMyDynamicTypeDescriptor(instance));
}
}
public class DynamicITypedList<T> : ObservableCollection<T>, /*List<T>, IList<T>,*/ ITypedList where T : IMyDynamic, new()
{
public string GetListName(PropertyDescriptor[] listAccessors)
{
return null;
}
public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
{
return TypeDescriptor.GetProperties(this.FirstOrDefault());
}
}
}
this is not really an answer to the question directly, but...
I had the same task some days ago. Bind dynamic objects to a datagrid.
My solution is:
Add the columns to the datagrid manually
Set the databinding-properties manually
Use BindingSource, bind this BindingSource to your List then bind your grid to the bindingsource
Be sure to do all of this in the correct order, because if you don't, your dynamic properties are unknown to the grid/bindingsource and therefore won't be shown.
I don't remember the exact order of all of this, maybe you should try around a little with my hints and come back and ask further?

C# Custom CheckBox + Custom Binding Data Type

I created my own checkbox (UserControl). It has a property called ControlSource which works as the binding source. However, the Data Type of ControlSource is also a custom type. After playing around,
...
[System.ComponentModel.Bindable(true), Browsable(true), Category("Behavior")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public IMyBool ControlSource
{
get { return this.chx.Checked ? IMyBool.True : IMyBool.False; }
set { this.chx.Checked = value.Value; }
}
...
I tried an interface solution here:
public interface IMyBool
{
bool Value { get; set; }
IMyBool True { get; }
IMyBool False { get; }
}
public class MyBool
{
protected bool? _bValue = null;
protected string _sTrue = String.Empty;
protected string _sFalse = String.Empty;
protected string _sNull = String.Empty;
public MyBool(bool? bValue = null)
{
this._bValue = bValue;
}
public override string ToString()
{
return this._bValue.HasValue ? (this._bValue.Value ? _sTrue : _sFalse) : _sNull;
}
public bool Value
{
get { return this._bValue.Value; }
set { this._bValue = value; }
}
}
public class MyInvoiceBool : MyBool, IMyBool
{
public static implicit operator MyInvoiceBool(bool? bValue)
{
return bValue.HasValue ? (bValue.Value ? True : False) : Null;
}
public static implicit operator bool?(MyInvoiceBool ivbValue)
{
return ivbValue._bValue;
}
public MyInvoiceBool(bool? bValue = null)
{
base._sTrue = "Rechnung wird gestellt";
base._sFalse = "Rechnung wird nicht gestellt";
base._bValue = bValue;
}
public static MyInvoiceBool True
{
get { return new MyInvoiceBool(true); }
}
public static MyInvoiceBool False
{
get { return new MyInvoiceBool(false); }
}
public static MyInvoiceBool Null
{
get { return new MyInvoiceBool(); }
}
}
public class MyInvoiceAddressBool : MyBool
{
public static implicit operator MyInvoiceAddressBool(bool? bValue)
{
return bValue.HasValue ? (bValue.Value ? True : False) : Null;
}
public static implicit operator bool?(MyInvoiceAddressBool ivbValue)
{
return ivbValue._bValue;
}
public MyInvoiceAddressBool(bool? bValue = null)
{
base._sTrue = "Abweichende Rechnungsadresse";
base._bValue = bValue;
}
public static MyInvoiceAddressBool True
{
get { return new MyInvoiceAddressBool(true); }
}
public static MyInvoiceAddressBool False
{
get { return new MyInvoiceAddressBool(false); }
}
public static MyInvoiceAddressBool Null
{
get { return new MyInvoiceAddressBool(); }
}
}
My aim is that I can use my own bool data type which knows an alternative string expression for true, false or null. However, the groupbox control should be coded generally. That's why an interface solution came into my mind. However, it does not work. I am pretty sure that there is a "often used" solution, isn't it?
Finally, I chose a work around: I inherited the checkbox and explicitly used my custom data type for the control source property. Thus, I do not need an interface or abstract class... Its not the best solution.
Rather than extending the data type, what about implementing an IValueConverter to generate the string representation?
http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx

Can I make Raven DB serialize an object as it would a string, if i have created an implicit type conversion operator?

I have a class that looks something like this:
public class MyClass
{
string _value;
public static implicit operator MyClass (string value)
{
return new MyClass(value);
}
MyClass(string value)
{
// Do something...
_value = value;
}
public override string ToString()
{
// Do something...
return _value;
}
}
Hence, I can use the class like this:
MyClass a = "Hello!";
But in Raven DB it will just be stored like
"SomeProperty": {}
since it has no public properties. And it is quite useless.
To solve this I would make the _value private member a public property instead, like this:
public string Value { get; set; }
and Raven DB will store
"SomeProperty": { "Value": "Hello!" }
and it will be deserializable.
But I don't want this public property. Can I somehow make Raven DB serialize and deserialize the class as was it would a string? Like:
"SomeProperty": "Hello!"
Hi I know this is old but I thought I would add some additions to Ayendes' reply to help people who like me had the same issue and spent hours looking on forums for an answer (of which there were a few but none had any example that you could follow), it's not hard to figure this out but with an example I could have solved this in 10 minutes as opposed to spending a few hours.
My problems was that we have custom value type structs in our application the example I will use is EmailAddress. Unfortunately in Ravendb we could not run queries against these types without defining a custom serialiser.
Our Value Type looked Like this:
[DataContract(Namespace = DataContractNamespaces.ValueTypes)]
public struct EmailAddress : IEquatable<EmailAddress>
{
private const char At = '#';
public EmailAddress(string value) : this()
{
if (value == null)
{
throw new ArgumentNullException("value");
}
this.Value = value;
}
public bool IsWellFormed
{
get
{
return Regex.IsMatch(this.Value, #"\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*");
}
}
public string Domain
{
get
{
return this.Value.Split(At)[1];
}
}
[DataMember(Name = "Value")]
private string Value { get; set; }
public static bool operator ==(EmailAddress left, EmailAddress right)
{
return left.Equals(right);
}
public static bool operator !=(EmailAddress left, EmailAddress right)
{
return !left.Equals(right);
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
return this.Equals(new EmailAddress(obj.ToString()));
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
public override string ToString()
{
return this.Value;
}
public bool Equals(EmailAddress other)
{
return other != null && this.Value.Equals(other.ToString(), StringComparison.OrdinalIgnoreCase);
}
}
The type of document we wanted to save and query would look something like this
public class Customer
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public EmailAddress Email { get; set; }
}
The custom serialiser to store our email as a raw string and then convert it back to its value type on retrieval looked like this:
public class EmailConverterTest : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(EmailAddress);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
EmailAddress actualAddress = new EmailAddress(reader.Value.ToString());
return actualAddress;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
EmailAddress actualAddress = (EmailAddress)value;
string stringEmail = actualAddress.ToString();
writer.WriteValue(stringEmail);
}
}
Finally I wired it up and was able to query everything as follows:
public static void serializercustom(Newtonsoft.Json.JsonSerializer serialiser)
{
serialiser.Converters.Add(new EmailConverterTest());
}
public static void TestCustomer()
{
using (var documentStore = new DefaultDocumentStore())
{
documentStore.ConnectionStringName = Properties.Settings.Default.SandBoxConnection;
documentStore.Initialize();
documentStore.Conventions.CustomizeJsonSerializer = new Action<Newtonsoft.Json.JsonSerializer>(serializercustom);
var customer = new Customer
{
Id = Guid.NewGuid(),
FirstName = "TestFirstName",
LastName = "TestLastName",
Email = new EmailAddress("testemail#gmail.com")
};
// Save and retrieve the data
using (var session = documentStore.OpenSession())
{
session.Store(customer);
session.SaveChanges();
}
using (var session = documentStore.OpenSession())
{
var addressToQuery = customer.Email;
var result = session.Query<Customer>(typeof(CustomerEmailIndex).Name).Customize(p => p.WaitForNonStaleResults()).Where(p => p.Email == addressToQuery);
Console.WriteLine("Number of Results {0}", result.Count()); // This always seems to return the matching document
}
}
}
You can write a JsonConverter and teach RavenDB how you want to store the data.
After you write the converter, register it in the store.Conventions.CustomizeSerializer event.

Parameterizing propertynames using expressions

I am having a piece of code in which i delegate certain properties of a class to another class if the class exists. Below you see the start time being defined on the TimeProvider if it exists.
public override DateTime StartTime
{
get
{
return (TimeProvider != null) ? TimeProvider.StartTime : base.StartTime;
}
set
{
if (TimeProvider != null)
{
TimeProvider.StartTime = value;
}
else
{
base.StartTime = value;
}
}
}
Now my 'problem' is that i have a lot more properties (like endtime,currentime) i delegate to the TimeProvider if it is not null. So i would like to have code like:
public override DateTime StartTime
{
get
{
return GetTime(()=>StartTime);
}
set
{
SetTime(()=>StartTime)
}
}
Where the ()=>StartTime expression is sometimes 'evaluated' on the TimeProvider and sometimes on the class itself (they share a baseclass). Can something like this be done? Preferably without using reflection.
Cake
public class Foo
{
private string _string1;
public Foo foo { get; set; }
private T GetProperty<T>(Func<Foo,T> getter)
{
return foo == null
? getter(this)
: getter(foo);
}
private void SetProperty(Action<Foo> setter)
{
if (foo == null)
setter(this);
else
setter(foo);
}
public string String1
{
get { return GetProperty(a => a._string1); }
set { SetProperty(a => a._string1 = value); }
}
}

Categories

Resources