Using "this" keyword on object members on initialization - c#

I got a delegate for OnBuy and OnSell of my items objects, the problem is I'm going to copy paste some of items and not modify the keyword name for each OnBuy and OnSell and try to use "this" keyword, I've added my function to the item class, but still can't access it without modifying the object name after copy paste. Here's my codes:
public static Item item = new Item
{
Name = "Item",
ID = 1,
Price = 50,
Info = "Awesome!",
OnBuy = delegate(Client cli)
{
// Invalid
this.BuyTitle(cli);
// Still can't change
this.Name = "AAA";
return true;
},
OnSell = delegate(Client cli)
{
// Invalid
this.SellTitle(cli);
// Still can't change
this.Name = "AAA";
return true;
}
}
And here's the item class:
public class Item
{
public string Name { get; set; }
public int ID { get; set; }
public int Price { get; set; }
public string Info { get; set; }
public Func<Client, bool> OnBuy { get; set; }
public Func<Client, bool> OnSell { get; set; }
public bool BuyTitle(Client cli)
{
...
}
public bool SellTitle(Client cli)
{
...
}
}

You are using object initializer syntax to create an instance of Item. It is not possible for the anonymous delegate to use this because it is not possible to for an object initializer to reference the object it is creating. From section 7.6.10.2 of the C# spec:
It is not possible for the object initializer to refer to the newly created object it is initializing.
I'm not sure that delegates are the most appropriate mechanism here, but if you still want to use them, I would create a static method which creates the item and call that to initialize the static field.
Here is an outline of what you can do:
public static Item item = CreateItem();
private static Item CreateItem()
{
var item = new Item() { Name = "Item" };
item.OnBuy = client => { item.OnBuy(client); item.Name = "AAA" };
return item;
}

Related

Get the value from object of a class by property name dynamically in c#

I want to write a method that should return the value from an object for the specified property.
public class MyClass
{
public int a { get; set; }
public int b { get; set; }
public int c { get; set; }
public int d { get; set; }
}
public int GetValue(string field)
{
MyClass obj=new MyClass();
obj=FromDb(); //get value from db
dynamic temp=obj;
return temp?.field;
}
The above code is only to demonstrate to what I am looking for.
Here I want to pass the property name (i.e a/b/c/d as per my above code) as an input to the method GetValue and it should return the value of that property.
This code is compiling successfully, but in run time it will search for the property name field not the value of field variable.
Any suggestions or workaround will be appreciated.
You can use reflection to get the value:
public int GetValue(string field)
{
MyClass obj = new MyClass();
obj = FromDb(); //get value from db
var property = obj.GetType().GetProperty(field);
return (int)property.GetValue(obj);
}

Can you declare a List of a class within another class?

I am trying to create a simple order sheet that has products, customers, order lines, and an order sheet. Currently, I am just hardcoding in products and customers for simple testing purposes. With the order sheet, I want to have a List of the order line items (contains quantity and price from products, and a few other bits of information) in the order class. When I create the order in the program, it's not creating the List of order line items that I have in the constructor. I have tried to .Add within the constructor which didn't work as well in the program, in the program it states it does not contain the definition Add.
When I try to access .test it shows as NULL.
namespace ObjectsCSharpe.Library
class Order
{
public Order()
{
var testLine = new List<OrderLineItems>();
}
public List<OrderLineItems> testLine { get; set; }
}
class OrderLineItems
{
public OrderLineItems()
{
this.orderID = 0;
this.lineNumber = 0;
this.product = new Product();
this.quantity = 0;
this.test = "OLI";
this.lineTotal = 0.00;
}
public int orderID { get; set; }
public int lineNumber { get; set; }
public Product product { get; set; }
public int quantity { get; set; }
public string test { get; set; }
public double lineTotal { get; set; }
}
class Program
{
static void Main(string[] args)
{
Order orderSheet = new Order();
OrderLineItems temp456 = new OrderLineItems();
orderSheet.testLine.Add(temp456);
string abc = orderSheet.testLine[0].test;
Console.WriteLine(abc);
}
}
I'll start with this excerpt:
public Order()
{
var testLine = new List<OrderLineItems>();
}
This is the constructor for the Order type. In this code, the var keyword means you are declaring a new variable, where the scope of the variable is limited to that method. The type also contains this:
public List<OrderLineItems> testLine { get; set; }
So there is a separate testLine variable in the type. But, in the constructor, the use of var means this other variable was not touched.
Later on we have this code:
orderSheet.testLine.Add(temp456);
Unfortunately, because of the earlier mistake, orderSheet.testLine is still null, and you can't call a method on a null reference.
You can fix this as easily as removing var from the constructor:
public Order()
{
testLine = new List<OrderLineItems>();
}
or, even better, remove the entire constructor from the type completely. Initialize the list property where it is declared and make it get-only:
public class Order
{
public List<OrderLineItems> testLine {get;} = new List<OrderLineItems>();
}
(Note: You can still add items to get-only List property.)
I think you need to make public keyword while creating all your class.
public class Order{
//Add Your class declaration...
}

Dynamically get property from select function using variable

I'm trying to dynamically get all the values of a specific property from all class instances. I've managed to do it with one property
public class fighter
{
public string Name { get; set; }
public double Height { get; set; }
}
fighter[] roster[5] = new fighter();
string namearray = roster.Select(x => x.Name).ToArray();
int weightarray = roster.Select(x => x.Weight).ToArray();
However I want to reference the property with a variable and put it in a loop so I don't need a select function for every property. Is there anyway to do this, or any other method to get all values of a property from all objects where this could work?
class Program
{
static void Main(string[] args)
{
stud stud = new stud() { id=10,name="test" };
PropertyInfo[] propertyInfo;
propertyInfo = typeof(stud).GetProperties(BindingFlags.Public|BindingFlags.Instance);
foreach (var item in propertyInfo)
{
Console.WriteLine(item.Name + " : " + item.GetValue(stud));
}
Console.ReadLine();
}
}
public class stud {
public int id { get; set; }
public string name { get; set; }
}
use following code, i have created a propertyInfo class from System.Reflection namespace which allows to get property names of the class. after which once you get all the names of properties can be accessed using propertyinfo.GetValue function.

Recursive PropertyInformation from Nested IEnumerable<Model>

I am having trouble getting the property Names of the IEnumerable properties in my models. I cant seem to get the Nested IEnumerables from the TModel classes. I have looked into some reflection examples but haven't something quite along these lines.
I am looking to just get the IEnumerable property names for each nested model and send the property name to a list. The actual value is not important.
Any help would be greatly appreciated.
// TModel = DataContent in this context.
public class GetModelBase<TModel>
{
public string Error { get; set; }
public IEnumerable<TModel> DataContent { get; set; }
}
public class DataContent
{
public int Total { get; set; }
public IEnumerable<Data> Data { get; set; }
}
public class Data
{
public int DataId{ get; set; }
IEnumerable<DataInformation> DataInformation{ get; set; }
}
public IEnumerable<GetModelBase<TModel>> ResponseAsList<TModel>()
{
// ResponseBody in this context is a string representation of json of the models above...
var toArray = new ConvertJsonArray<GetModelBase<TModel>>(ResponseBody).ReturnJsonArray();
}
// T = GetModelBase<DataContent> in this context.
public class ConvertJsonArray<T>
{
public ConvertJsonArray(string responseString)
{
_responseString = responseString;
Convert();
}
public void Convert()
{
var result = JObject.Parse(_responseString);
// This is where I am having trouble... I am unable to get the nested IEnumerable names.
Type t = typeof(T);
PropertyInfo[] propertyInformation = t.GetProperties(BindingFlags.Public|BindingFlags.Instance);
List<string> toLists = new List<string>();
foreach (PropertyInfo pi in propertyInformation)
toLists.Add(pi.Name);
// End of Property Information Issuse...
foreach (string s in toLists.ToArray())
{
if (result[s] != null)
{
if (!(result[s] is JArray)) result[s] = new JArray(result[s]);
}
}
_jsonAsArray = result.ToString();
}
public string ReturnJsonArray()
{
return _jsonAsArray;
}
private string _responseString { get; set; }
private string _jsonAsArray { get; set; }
}
The result I am looking for in the above code sample would be a list containing only the IEnumerable names as such { "DataContent", "Data", "DataInformation" }
UPDATE:
I am still having trouble looping through each model. I have a nearly working code example.
// This replaces the Type code in the Convert method...
GetProperties(typeof(T))
private void GetProperties(Type classType)
{
foreach (PropertyInfo property in classType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (property.PropertyType.IsGenericType && (property.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
{
ValuesToList.Add(property.Name);
foreach (Type nestedType in property.PropertyType.GetGenericArguments())
{
GetProperties(nestedType);
}
}
}
}
private List<string> ValuesToList { get; set; }
The results for this yields { "DataContent", "Data" } but fails to get "DataInformation". For some reason the IEnumerables are not hit while in the foreach loop. Additional help would be appreciated.
You already have the PropertyInfo, so you are almost there - all that is left is to recognize which properties are of type IEnumerable<...>, where ... can be an arbitrary type.
For this purpose, check the PropertyType property.
It is a Type instance for which you can check whether it is based upon the generic type definition IEnumerable<T> by means of the GetGenericTypeDefinition method.
That method will throw an exception for non-generic types, so you will also have to check IsGenericType:
if (pi.PropertyType.IsGenericType
&& (pi.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
{
toLists.Add(pi.Name);
}

Return a List<SomeObject> without a certain property using Linq in c#?

I have an object containing different properties like the object below:
public class CompressedLogResponse
{
public string LoggerType { get; set; }
public int NumberOfRegisters { get; set; }
public int NewLogId { get; set; }
public DateTime LoggerAnnounceTime { get; set; }
public List<Log> Log{ get; set; }
}
How can I return a List of this objekt that does not include the List<Log> Log property?
Linq would be preffered
Thanks for any help that you can provide
You cannot just hide a property of a class (you declared it a as public)
Option 1:
Althought as Robson wrote you can set it null (thats not very reliable thaught cause nobody expects a class containing a property that is always null)
Option2:
If you consume the class on the same place use a anonymous type as Mez wrote, althought it sounds like you want to hide the Property from external usage. (I don't like the dynamic approach, the dynamic keyword was made for interop/DOM not for transporting anonymous types.)
Option3:
If you want a List of this type to be returned without the Log property, you have to create a new class (Inheritance is a good way to realize this):
public class CompressedLogResponseBase
{
public string LoggerType { get; set; }
public int NumberOfRegisters { get; set; }
public int NewLogId { get; set; }
public DateTime LoggerAnnounceTime { get; set; }
}
public class CompressedLogResponse : CompressedLogResponseBase
{
public List<Log> Log{ get; set; }
}
Now you can return a list of base items (that do not have a Log property at all)
public List<CompressedLogResponseBase> ReturnWithoutLog(IEnumerable<CompressedLogResponse> items)
{
return ((IEnumerable<CompressedLogResponseBase>)items).ToList();
}
If a IEnumerable as return type is suficient it becomes really easy
public IEnumerable<CompressedLogResponseBase> ReturnWithoutLog(IEnumerable<CompressedLogResponse> items)
{
return items
}
whith "does not include the List Log property" i guess you mean that the property "public List Log" will be blanked but still there, so you can just null that property out, because if you create an object that doesn't contain the "public List Log" property, than it will not be a "CompressedLogResponse" but will be another type.
List<CompressedLogResponse> listOne = new List<CompressedLogResponse>();
//....
//fill the listOne
//....
List<CompressedLogResponse> listWithoutListLog = (from item in listOne
select new CompressedLogResponse(
LoggerType = item.LoggerType,
NumberOfRegisters = item.NumberOfRegisters ,
NewLogId = item.NewLogId ,
LoggerAnnounceTime = item.LoggerAnnounceTime ,
Log= null)).ToList();
You can return an anonymous list of your original list like the following;
public static List<dynamic> Test() {
List<CompressedLogResponse> list = new List<CompressedLogResponse>();
var result = list.Select(x => new
{
x.LoggerAnnounceTime,
x.LoggerType,
x.NewLogId,
x.NumberOfRegisters
});
return result.ToList<dynamic>();
}
Take a look at the .Select(), and also the dynamic keyword.
Then to call it,
var x = Test();
foreach(dynamic o in x)
{
int NumberOfRegisters;
//You have 2 ways... either by
NumberOfRegisters = o.NumberOfRegisters;
// or reflection
NumberOfRegisters = o.GetType().GetProperty("NumberOfRegisters").GetValue(o, null);
}

Categories

Resources