I would like to know if there is a way to know if a parameter has been set. For example I have my object User.
public class User{
public int Oid{ get; set; }
public string Name{ get; set; }
public string Test{ get; set; }
}
I create an instance of my object and I set the property Oid and Name but not Test. I would like know this.
User u = new User();
u.Oid = 1;
u.Name = "Test";
It's possible?
TY
For reference types, a property (or field) which is not set will have the value null. Because string is a reference type, you can check this very easy:
if(u.Test == null)
{
Console.WriteLine("Property test of variable u is not set!");
}
For other types it is not so easy. bool variables will be false by default, and all numeric values like int uint, double etc will be 0. But of course, somebody might have set it fully aware to these values.
You can get the default value of any type via the following:
int x = default(int); // will be 0
string y = default(y); // will be null
bool z = default(bool); // will be false;
ADDENDUM: A completely different approach will be the following:
public class User{
public int Oid{ get; set; }
public string Name{ get; set; }
private string test;
public string Test
{
get { return test; }
set {test = value; IsTestSet = true; }
}
public bool IsTestSet {get; private set;}
}
With this code, you can check the property IsTestSet to determine whether the setter was called at least once.
This's my personal solution.
public short oid;
public short Oid
{
get { return oid; }
set
{
oid = value;
AddListaSet("Oid");
}
}
// for all parameter
List<string> ListSet { get; set; } = new List<string>();
private void AddListSet(string name)
{
if (ListSet.Contains(name) == false)
ListSet.Add(name);
}
public bool IsSet(string name)
{
return ListSet.Contains(name) ? true : false;
}
Related
How to serialize a generic(T) object which can hold any type of data (int / string / DateTime) using Protobuf-net. Following is my code
[ProtoContract]
public class E1DataRow
{
[ProtoMember(1)]
public List<NameValue> NameValues { get; set; }
public E1DataRow()
{
NameValues = new List<NameValue>();
}
public void AddNameValue(string name, object obj, Type type)
{
NameValues.Add(new NameValue { Name = name, Value = obj, ValueType = type });
}
}
[ProtoContract]
public class NameValue
{
[ProtoMember(1)]
public string Name { get; set; }
[ProtoMember(2)]
public object Value { get; set; }
[ProtoMember(3)]
public Type ValueType { get; set; }
}
serialization code
var e1DataRows = new List<E1DataRow>();
/*
Code to add Data rows to e1DataRows
e1DataRow.AddNameValue(column.ColumnName, value, column.TypeOfColumn);
*/
using (var stream = File.OpenWrite(path))
{
Serializer.Serialize(stream, e1DataRows);
}
[ProtoMember(2, DynamicType = true)]
public object Value { get; set; }
Above code throws following error (DynamicType = true)
ProtoMemberAttribute.DynamicType' is obsolete: 'Reference-tracking and dynamic-type are not currently implemented in this build; they may be reinstated later; this is partly due to doubts over whether the features are adviseable, and partly over confidence in testing all the scenarios (it takes time; that time hasn't get happened); feedback is invited'
It would be great if you can help with how to serialize a List using Protobug-net. Thanks...
You may want to look at https://github.com/dotarj/protobuf-net-data - this isn't affiliated with protobuf-net (different authors etc), but it uses protobuf-net to perform serialization of DataTable and data-readers, so it might do what you want ready-made.
As for implementing it yourself:
protobuf-net does not support object (or dynamic, which is just a fancy way of spelling object), fundamentally. There are ways of working around this, essentially similar to the oneof handling in protobuf - i.e. something like (in protobuf terms):
message Foo {
oneof payload {
string payload_string = 1;
bool payload_bool = 2;
int32 payload_int32 = 3;
float payload_float = 4;
// etc
}
}
This is pretty easy to put together in protobuf-net thanks to "conditional serialization", which means you could do something like:
public object Value { get; set; }
[ProtoMember(1)]
public string ValueString
{
get => (string)Value;
set => Value = value;
}
public bool ShouldSerializeValueString()
=> Value is string;
[ProtoMember(2)]
public string ValueBoolean
{
get => (bool)Value;
set => Value = value;
}
public bool ShouldSerializeValueBoolean()
=> Value is string;
// etc
If on c# >= 4 you might want to try the following:
[ProtoContract]
public class E1DataRow
{
[ProtoMember(1)]
public List<NameValue<dynamic>> NameValues { get; set; }
public E1DataRow()
{
NameValues = new List<NameValue<dynamic>>();
}
public void AddNameValue(string name, dynamic obj)
{
NameValues.Add(new NameValue<dynamic> { Name = name, Value = obj });
}
}
public class NameValue<T>
{
[ProtoMember(1)]
public string Name { get; set; }
[ProtoMember(2)]
public T Value { get; set; }
[ProtoMember(3)]
public Type ValueType { get { return Value.GetType(); } }
}
Not sure if Protobuf-net likes the List<NameValue<dynamic>>, can't test it as of now.
ProtoMember(3) at ValueType possibly is not necessary as of being readonly anyways.
I have this class:
public class Test
{
public string Id { get; set; }
public int Number { get; set; }
public int DoubleNumber { get; set; }
}
and a list
List<Test> myTestList;
How can I make the value of the field DoubleNumber in myTestList equal to twice the value of Number? Note that I am okay to create another list if that's needed.
If I understand your question correctly:
foreach(Test item in myList) {
item.DoubleNumber = 2*item.Number;
}
Or, if it's ok, just remove the setter and modify the getter to return 2x Number:
public class Test
{
public string Id { get; set; }
public int Number { get; set; }
public int DoubleNumber { get { return 2* this.Number; } } //completely remove setter
}
Or, if you still want to be able to modify DoubleNumber:
public class Test {
private int m_num;
private int m_doubleNum;
public string Id {
get;
set;
}
public int Number {
get {
return this.m_num;
}
set {
this.m_num = value;
this.m_doubleNum = 2 * value; //when Number is set, update m_doubleNum too
}
}
public int DoubleNumber {
get {
return this.m_doubleNum;
}
set {
this.m_doubleNum = value; //allow manual setting of DoubleNumber
//or maybe also modify Number here?
//this.m_num = value / 2;
}
}
}
One way it could be using a foreach statement:
foreach(var item in myTestList)
{
item.DoubleNumber = 2*item.Number;
}
Another way it could be to use LINQ.
var result = myTestList.Select(test => new Test
{
test.Id,
test.Number,
DoubleNumber = 2*test.Number;
})
.ToList();
Among the two ways I would prefer the first one, since it's more clear what you are trying to do and more performant (in the second approach you have to create a new object for each object in myTestList).
How can I access the custom attribute of the parent or owner object.
Look at the FieldInfo property of the SQLFieldInfo struct
Here's a more detailed program that will compile and run that shows what I need.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Employee myclass = new Employee();
// Load from sql server...
myclass.Name = "Alain";
myclass.Age = 51;
//----
MessageBox.Show(myclass.Name.ToString()); // Should return Alain
MessageBox.Show(myclass.Age.FieldInfo.Type.ToString()); // Should output "int"
}
}
// This next class is generated by a helper exe that reads SQL table design and create the class from it
[SQLTableAttribute(DatabaseName = "Employees", Schema = "dbo", TableName = "Employees")]
public class Employee
{
[SQLFieldAttribute(FieldName = "ID", Type = SqlDbType.Int)]
public SQLFieldInfo<int> ID { get; set; }
[SQLFieldAttribute(FieldName = "Name", Type = SqlDbType.NVarChar, Size = 200)]
public SQLFieldInfo<String> Name { get; set; }
[SQLFieldAttribute(FieldName = "Age", Type = SqlDbType.Int)]
public SQLFieldInfo<int> Age { get; set; }
}
public struct SQLFieldInfo<T>
{
private readonly T value;
public SQLFieldInfo(T Value)
{
this.value = Value;
}
public static implicit operator SQLFieldInfo<T>(T Value)
{
return new SQLFieldInfo<T>(Value);
}
public T Value
{
get
{
return this.value;
}
}
public override string ToString()
{
return this.value.ToString();
}
public SQLFieldAttribute FieldInfo
{
get
{
// Need to retreive the attribute class of the parent or declaring member
return null;
}
}
}
// Holds the sql field information
public class SQLFieldAttribute : Attribute
{
public string FieldName { get; set; }
public SqlDbType Type { get; set; }
public bool AllowNull { get; set; }
public int Size { get; set; }
}
// Holds the sql table information
public class SQLTableAttribute : Attribute
{
public string DatabaseName { get; set; }
public string Schema { get; set; } = "dbo";
public string TableName { get; set; }
}
Thank you!
Alain
My data class is as follows (should be fairly translatable to A above):
public class Foo
{
[Argument(Help = "Name", AssignmentDelimiter = "=")]
public string Name
{
get;
set;
}
}
A helper class is responsible of reading attribute values of objects:
static public string GetCommandLineDelimiter<T>(Expression<Func<T>> property)
{
if(property != null)
{
var memberExpression = (MemberExpression)property.Body;
string propertyName = memberExpression.Member.Name;
PropertyInfo prop = typeof(Arguments).GetProperty(propertyName);
if(prop != null)
{
object[] dbFieldAtts = prop.GetCustomAttributes(typeof(ArgumentAttribute), true);
if(dbFieldAtts.Length > 0)
{
return ((ArgumentAttribute)dbFieldAtts[0]).AssignmentDelimiter;
}
}
}
return null;
}
To use it, simply:
string delimiter = GetCommandLineDelimiter(() => myObject.Name);
That will get the attribute value of AssignmentDelimiter on property Name, i.e. "=".
First, MSDN is your friend.
Then, if you want to get the attributes for ancestors just specify true in the inherit flag of the method:
var attribute = typeof(A).GetProperty("myprop").GetCustomAttributes(true)
.OfType<MycustomAttrib>().FirstOrDefault();
This works. I am doing a lazy initialization of a reference to the custom attribute by using reflection to look at all the properties of all the types.
public class MycustomAttribAttribute : Attribute
{
public MycustomAttribAttribute(string name)
{
this.Name=name;
}
public string Name { get; private set; }
}
class A
{
public A() { MyProp=new B(); }
[MycustomAttrib(name: "OK")]
public B MyProp { get; set; }
}
class B
{
private static Lazy<MycustomAttribAttribute> att = new Lazy<MycustomAttribAttribute>(() =>
{
var types = System.Reflection.Assembly.GetExecutingAssembly().DefinedTypes;
foreach(var item in types)
{
foreach(var prop in item.DeclaredProperties)
{
var attr = prop.GetCustomAttributes(typeof(MycustomAttribAttribute), false);
if(attr.Length>0)
{
return attr[0] as MycustomAttribAttribute;
}
}
}
return null;
});
public string MyProp2
{
get
{
return att.Value.Name;
}
}
}
class Program
{
static void Main(string[] args)
{
// Finds the attribute reference and returns "OK"
string name = (new A()).MyProp.MyProp2;
// Uses the stored attribute reference to return "OK"
string name2 = (new A()).MyProp.MyProp2;
}
}
I am trying to define get; set; value when initializing an attribute.
I have the following interface
public interface IReportColumn
{
string Title { get; set; }
string ColumnKey { get; }
AggregateFunctions AggregateFunction { get; set; }
string SqlAlias { get; }
}
What I need to do is set the attribute SqlAlias to a random string if AggregateFunction == AggregateFunctions.None || ColumnKey == null. But, since I am generating a random string here, I don't want it to change ever time I call the get method. I want to be able to get it, set it and reuse the same value through the entire request.
This is how I am implementing my interface
public class ReportColumnMsSqlServer : IReportColumn
{
public string Title { get; set; }
public string ColumnKey { get; set; }
public AggregateFunctions AggregateFunction { get; set; }
public string SqlAlias {
get {
return this.GetColumnName();
}
}
private string GetColumnName()
{
string columName = this.ColumnKey;
if (columName == null || this.AggregateFunction != AggregateFunctions.None)
{
columName = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
}
return string.Format("{0}", new Regex("[^a-zA-Z0-9]").Replace(columName, string.Empty));
}
}
How can I set the SqlAlias value only once based on my condition above and keep the same value through the entire request?
You can introduce a new private field to store the information, and only calculate the value the first time it's accessed:
private string _sqlAlias = null;
public string SqlAlias {
get {
if (_sqlAlias == null)
_sqlAlias = this.GetColumnName();
return _sqlAlias;
}
}
Depending on your use case, since the return value is based on both the ColumnKey and the AggregateFunction, you could implement the setters of both of those properties to set _sqlAlias back to null, so further calls to SqlAlias will recalculate the new value, based on the other updated properties.
Use a simple "lazy loading" pattern.
private string _sqlAlias;
public string SqlAlias {
get {
if (_sqlAlias == null) {
_sqlAlias = GetColumnName();
}
return _sqlAlias;
}
}
I have following classes. In instance of BE (let's say objBE) i want to select property name on run time and assign it's value. e.g. we have a combo with all properties populated, and have text box and command button on window form. I want to select property name from the combo and type some value in text box and on button click i want to find the property name from the objBE and assign the text box value to the selected property. Couldn't get way how to get it done. Can some help.
Thanks in Advance.
H N
public class MyPropertyBase
{
public int StartOffset { get; set; }
public int EndOffset { get; set; }
}
public class MyProperty<T> : MyPropertyBase
{
public MyProperty(T propertyValue)
{
PropertyValue = propertyValue;
}
public T PropertyValue { get; set; }
public static implicit operator MyProperty<T>(T t)
{
return new MyProperty<T>(t);
}
}
public class BE
{
private List<Admin_Fee> _Admin_Fee = new List<Admin_Fee>();
public MyProperty<int> RFID
{get;set;}
public MyProperty<string> CUSIP
{get;set;}
public MyProperty<string> FUND_CITY
{get;set;}
public MyProperty<int> SomeOtherProperty { get; set; }
//public List<MyPropertyBase> MyDataPoints { get; set; }
public List<Admin_Fee> Admin_Fee
{
get{return _Admin_Fee;}
set{}
}
}
You can use GetProperty on the Type, then use SetValue on the PropertyInfo instance. Based on your description, I think you want something like this:
void Main()
{
BE be = new BE();
SetMyPropertyValue("RFID", be, 2);
SetMyPropertyValue("CUSIP", be, "hello, world");
Console.WriteLine(be.RFID.PropertyValue);
Console.WriteLine(be.CUSIP.PropertyValue);
}
private void SetMyPropertyValue(string propertyName, object instance, object valueToSet)
{
Type be = instance.GetType();
Type valueType = valueToSet.GetType();
Type typeToSet = typeof(MyProperty<>).MakeGenericType(valueType);
object value = Activator.CreateInstance(typeToSet,valueToSet);
var prop = be.GetProperty(propertyName);
prop.SetValue(instance, value, null);
}