I'm trying to work out if the following is possible, I've done lots of googling and I'm a bit confused. I'm pretty sure I can work out the class reflection on the object class and updating the database isn't a problem once I have the loop, but I can't work out if this is possible at all.
If I was doing this with a fixed class object it'd be easy I'd just do:
public void updateDB(obj_Users myObject)
But as I have a lot of class objects that will take a long time, so trying to make it more dynamic.
Here is a sample of a class I want to pass through (but could be anything following the same format):
public class obj_Users
{
public Int32 UserID { get; set; }
public String UserName { get; set; }
public String FirstName { get; set; }
public String Surname { get; set; }
public String Email { get; set; }
public Int32 UserRole { get; set; }
public Int32 UserCompanyID { get; set; }
public String UserPassword { get; set; }
public Boolean IsAdmin { get; set; }
public String SessionKey { get; set; }
}
Here is some pseudocode of what I'm trying to achieve to explain:
public void updateDB(AnyClassObject obj_Users)
{
// Loop through obj_Users and grab the properties
// DB update call
}
This:
public void updateDB(object paramobj)
{
foreach(var prop in paramobj.GetType().GetProperties())
{
//grab
}
// update
}
Try this to loop to get the properties
foreach(var prop in obj_Users.GetType().GetProperties()) {
//use your props
}
You just need your parameter to be of type object to pass an instance of any class or struct.
public void updateDB(object whatever)
{
foreach(var prop in whatever.GetType().GetProperties())
{
... //do stuff
}
}
If you're stuck with the problem of having to deal with different classes, a generic method should fit your needs:
public void UpdateDB<T>(T obj)
{
var properties = typeof(T).GetProperties();
foreach (var prop in properties)
{
// Here you loop through the properties.
}
}
Related
how to convert dynamic variable to specific class.
dynamic variable has the same properties as my specific class.
public class PracovnikHmotZodpovednostDropDownListItem
{
[Column("ZAZNAM_ID")]
public int? ZaznamId { get; set; }
[Column("TEXT")]
public string Text { get; set; }
[Column("VALL")]
public int Value { get; set; }
public bool Disabled { get; set; } = false;
public UpdateStatusEnum UpdateStatus { get; set; }
}
void someMethod(dynamic dtos){
List<PracovnikHmotZodpovednostDropDownListItem> dto =
(List<PracovnikHmotZodpovednostDropDownListItem>)dtos;
}
If all you know is that the properties have the same names, you're in duck typing territory, casting won't help you.
Good news is, it's trivial to do, just tedious:
var dtoList = new List<PracovnikHmotZodpovednostDropDownListItem>();
foreach(var dto in dtos)
dtoList.Add(new()
{
ZaznamId = dto.ZaznamId,
Text = dto.Text,
// etc..
});
I receive a list of Parent Objects(Devices) and would like to convert each Device Object into a subclass Object. The layout would looks something along the lines of:
public class Device
{
public string FimrwareVersion { get; set; }
public string DeviceName { get; set; }
public int Status { get; set; }
public string Alias { get; set; }
public string DeviceType { get; set; }
public string AppServerUrl { get; set; }
...
}
public class SmartLightBulb : Device
{
public string Model { get; set; }
public string Description { get; set; }
public string SoftwareVersion { get; set; }
public int State { get; set; }
// Turn On/Off
public async Task ToggleState()
{
// Toggle State
}
...
}
public class SmartPlug : Device
{
public string Model { get; set; }
public string Description { get; set; }
public string SoftwareVersion { get; set; }
public int State { get; set; }
// stay on for X
public async Task SetTimer()
{
// Set Timer
}
...
}
public class Lb100 : SmartLightBulb
{
public async Task ChangeBrightness(int brightness)
{
// Change Brightness
}
}
public class Lb200 : SmartLightBulb
{
public async Task ChangeBrightness(int brightness)
{
// Change Brightness
}
public async Task ChangeColor()
{
// Change Color
}
}
The issue is that I receive a list of Devices and I cannot downcast from Device to Lb100. I would Like for Lb100 to maintain all of the properties that were received from the Device Class, and also take the functionality of the Lb100. I have heard of reflection, but I have also heard that this is a very slow process and should be avoided when possible.
What would be perfect is if I could just go:
var device = new Device(){ Firmware = "V1.4"...};
var lb100 = (Lb100) device;
I also understand that the reason down casting is not possible is because when the parent object is created, it allocates just enough memory for the object of that type. Then when you try and cast it to a larger subclass, you are trying to fit that larger subclass into that allocated space.
From the research that I have gathered, this way of thinking when programming is incorrect, but no one really mentions the correct way of thinking through this issue. Other users mention that they create a constructor that manually sets each property equal to each other; but this seems like a major hassle for maintaining code, especially when more devices and models are being added. Thanks for any advice that you can provide!!
You can try to cast to subclass, you only need to verify if it can be casted.
public class Program
{
public static void Main(string[] args)
{
var smartLightBulb = new SmartLightBulb()
{
DeviceType = "deviceType",
Model = "model"
};
Output(smartLightBulb);
}
public static void Output(Device device)
{
var smartLightBulb = (device as SmartLightBulb);
if(smartLightBulb != null)
{
Console.WriteLine(smartLightBulb.Model);
}
}
}
public class Device
{
public string DeviceType { get; set; }
}
public class SmartLightBulb : Device
{
public string Model { get; set; }
}
You can down cast (from super to parent) as that's just removing fields.
E.g. an lb100 is a type of device.
But you can't up cast (from parent to super) as that needs additional data.
E.g. a device is not a type of lb100.
In C#, is it possible to read a class tree path in a string and access programmatically a value, given an instance of that class ?
For example:
public class LogGeometricModel
{
public double SmallEndDiameter { get; set; }
public double LargeEndDiameter { get; set; }
public class Log
{
public Guid Id { get; set; }
public LogGeometricModel GeometricModel { get; set; }
}
public class Solution
{
public DateTime TimeStamp { get; set; }
public double Price { get; set; }
public Log RotatedLog { get; set; }
}
The strings could be something like this (a path in the class tree):
SmallEndDiameter = "Solution/RotatedLog/GeometricModel/SmallEndDiameter"
LargeEndDiameter = "Solution/RotatedLog/GeometricModel/LargeEndDiameter"
Price = "Solution/Price"
Id = "Solution/Log/Id"
By reading those strings, I would like to access the actual values of SmallEndDiameter, LargeEndDiameter, Price and Id.
Absolutely possible yes.
public static object GetValue(object instance, string path)
{
object currentObject = instance;
foreach (string propertyName in path.Split('/'))
{
currentObject = currentObject
.GetType()
.GetProperty(propertyName)
.GetValue(currentObject, null);
}
return currentObject;
}
You don't need to include 'Solution' in the string. This obviously lacks error handling, which if you are parsing a string like this, you will want.
I am using Linq to Entity , Linq query returning a ToList() and storing multiple rows in DataSourcesModel class. Later i am using foreach to iterate items and store values in DataSourcesModelDTO, till here working fine.
Now question is DataSourcesModelDTO dto storing only one row value.
I am expecting it should store multiple row value. How to achieve this in extension method?
** var datasoruceModeltDTO = DataSourcesDTOTransformers.ToDTO(result);**
public static class DataSourcesDTOTransformers
{
public static DataSourcesModelDTO ToDTO(this List<DataSourcesModel> model)
{
if (model == null) { return null; }
var dto = new DataSourcesModelDTO();
ToDTO(model, dto);
return dto;
}
public static void ToDTO(List<DataSourcesModel> model1, DataSourcesModelDTO dto)
{
foreach (var model in model1)
{
dto.DataSourceConfigID = model.DataSourceConfigID.ToString();
dto.DataSourceID = model.DataSourceID.ToString();
dto.Name = model.Name;
dto.server = model.server;
dto.LastModified = model.LastModified;
dto.Instance = model.Instance;
}
}
}
[DataContract]
public class DataSourcesModelDTO
{
[DataMember]
public string DataSourceID { get; set; }
[DataMember]
public string DataSourceConfigID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string server { get; set; }
[DataMember]
public string Instance { get; set; }
[DataMember]
public bool Deleted { get; set; }
[DataMember]
public DateTime LastModified { get; set; }
[DataMember]
public DateTime LastSync { get; set; }
}
foreach (var model in model1)
{
dto.DataSourceConfigID = model.DataSourceConfigID.ToString();
You are setting the properties of the same dto object every time in the loop. I would rearrange your toDTO methiod to either:
take in a single DataSourcesModel object and return a single DataSourcesModelDTO object (calling the method from within a loop or Linq query), or
take in an IEnumerable<DataSourcesModel> and return an IEnumerable<DataSourcesModelDTO>
How to achieve this in extension method?
Not sure why you need an extension method, but the appropriate signature would be:
public static IEnumerable<DataSourcesModelDTO> ToDTOCollection (this IEnumerable<DataSourcesModel> model)
I'll let you work out what the implementation would be. Hint: You could create a List<DataSourcesModelDTO> within the method and populate it with new objects the same way you are now.
The sub class isn't derived from the main class, I'm just trying to differentiate them.
Even as I type this I can see it being impossible but I have some classes:
public class TransferServiceInformation {
public int ProviderId { get; set; }
public string PrePurchaseOverride { get; set; }
public bool PrePurchaseOverrideEnabled { get; set; }
}
and
public class TransferServiceProviderInformation {
public int ProviderId { get; set; }
public string PrePurchaseInfo { get; set; }
And I want it so that if I ever try to access myTransferServiceInformation.PrePurchaseOverride and PrePurchaseOverrideEnabled == false it should return PrePurchaseInfo from the TransferServiceProviderInformation with the same ID.
Is something like that even possible?
I'm just having a thought that a getter that requires a TransferServiceProviderInformation passed as an argument might work, and throw an exception if the IDs don't match. Is that the only solution? The thing is, I'd rather not have to dig through all the (thousands of lines of) code to change all the places were I (or someone else) has called this property.
This is just an idea:
Make a static list with instances inside your class and auto-fill it with using the constructor. Then you can check this list from outside for instances with the same id.
public class TransferServiceInformation
{
public int ProviderId { get; set; }
private string prePurchaseOverride;
public string PrePurchaseOverride
{
get
{
if(!PrePurchaseOverrideEnabled)
{
// Get instances from the other class where providerID matches
var instance = TransferServiceProviderInformation.Instances.Where(i => i.ProviderId == this.ProviderId).FirstOrDefault();
if(instance != null)
return (instance).PrePurchaseInfo;
}
return null; // If no match found
}
set
{
prePurchaseOverride = value;
}
}
private bool prePurchaseOverrideEnabled;
public bool PrePurchaseOverrideEnabled { get; set; }
}
public class TransferServiceProviderInformation
{
// Store your instances static
public static List<TransferServiceProviderInformation> Instances { get; set; }
public TransferServiceProviderInformation()
{
// Add every new instance to the list
Instances.Add(this);
}
public int ProviderId { get; set; }
public string PrePurchaseInfo { get; set; }
}
To-do's:
If an instance gets disposed, delete it from the list of instances.