I been search but have no luck with this, im trying to call a method in a class from a table in a DB this method call another that find a entry and fill the object however i want to pass this object to my instance of the class
public class ProductCategory
{
public int ProductCategoryID { get; set; }
public string Name { get; set; }
public Guid rowguid { get; set; }
public DateTime ModifiedDate { get; set; }
public void FindItem<T1>(T1 id)
{
try
{
var obj = Activator.CreateInstance(this.GetType());
obj = Dal.ObjFind(obj, id); //this fill the object
//i want something like
foreach properties in obj
this.propertie = obj.propertie
}
catch (Exception e)
{
throw e;
}
}
}
in a way that i can call that method like
ProductCategory test = new ProductCategory();
test.Find(1);
and after that my object is loaded, i would really appreciate any help with this and sorry for the bad English or if i not explain clearly
Regards
Ok i found a way to achieve as Pac0 say with reflection you can do this
public void FindItem<T1>(T1 id)
{
try
{
var obj = this;
// fill the object with the DB data
obj = Dal.ObjFind(new Production.ProductCategory(), id);
PropertyDescriptorCollection PropertyObj =
TypeDescriptor.GetProperties(this);
//iterating the properties in the instance of the class
foreach (PropertyDescriptor prop in PropertyObj)
{
//Get the value for each properties in the filled Obj
//and set that value for each properites in "this"
prop.SetValue (this,prop.GetValue(obj));
}
}
catch (Exception e)
{
throw e;
}
}
in that way you can call your instalce like "test.FindItem(1)" and the object will be load, thanks!
To get information at runtime about the some class durig runtime is called *reflection** (this term should help you in your searches)
To get all the properties of a Type, you can use Type.GetProperties() .
have a look at GetProperty as well.
With this, you should be able to achieve what you want.
However, I'm not convinced it's the simplest way to go. Probably someone will come up with a better way to solve your underlying issue.
Related
Initializing a class like this:
var x = new Item()
{
ID = (int)...,
Name = (string)...,
..
};
I am getting an InvalidCastException on one of the assignments. There are quite a lot of them and the exception occurs on the whole expression even if I run the debugger line-by-line. The exception doesn't give any clue either what it's trying to cast to what.
Is there a way to debug each assignment individually? I've seen the debugger separately stops 3 times on expressions like foreach(x in y) so it seems a little strange it isn't doing that here, and detracts from the attraction of using this handy initialization syntax. Maybe there is a more fine-grained debug step I can use?
Your question is "Is it possible to debug a struct/class initialization member by member?".
So, up front, I'm not directly answering that question as worded because when I carefully read the body of your post it sounds like the essential question is how to identify the 'smoking line' root cause of this InvalidCastException right when it happens.
What I've found in similar situations is that if Visual Studio can be made to break at the moment the InvalidCastException occurs i.e. on that specific line then the Call Stack and local variables are much more immediate and useful.
Unfortunately, 'break when thrown' is suppressed by Visual Studio default settings for many exception types. But it's very easy to turn on 'break when thrown' for ALL exceptions. Just change this default setting in the Exceptions window in Visual Studio from this:
to this:
This doesn't "always" help but it's a good start. It's so easy why not try that first to see if rapid resolution is possible. Hope this turns out to be useful in your case.
Not sure if this is an option in VS 2017, I only have 2019 at hand. In your settings under Options -> Debugging -> General, uncheck Step over properties and operators. Then set a break point at your initializer and step through it with F11 (Step-Into). You will hit each property setter until the exception is thrown.
Please excuse me if I am missing something (will delete if thats the case) but using an invalid cast like this:
struct Item
{
public int ID { get; set; }
public Derived Derived { get; set; }
}
public class Base
{
public string Name { get; set; }
}
public class Derived : Base
{
public string AdditionalProperty { get; set; }
}
var baseClass = new Base()
{
Name = "foo",
};
try
{
var x = new Item()
{
ID = (int)20,
Derived = (Derived)baseClass,
};
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
neatly catches the error like this
Unable to cast object of type 'Base' to type 'Derived'.
in vs2017
However this breaks on the first error, we might wanna initalize an object this way and log all cast errors withouth exiting the initialisation. We can do this by implementing our own casting for this sample:
public static T TryCast<T>(Object _object)
{
try
{
return (T)_object;
}
catch (Exception e)
{
Console.WriteLine($"Cant cast object of type {_object.GetType().ToString()} to object of type {typeof(T)}");
}
return default(T);
}
public static T TryCast<T>(IConvertible _object)
{
try
{
return (T)Convert.ChangeType(_object, typeof(T));
}
catch (Exception e)
{
Console.WriteLine($"Cant convert object of type {_object.ToString()} to object of type {typeof(T)}");
}
return default(T);
}
New types for demonstrating purposes
struct Item
{
public int ID { get; set; }
public double FooDouble { get; set; }
public Base Base { get; set; }
public Derived Derived { get; set; }
public string Bar { get; set; }
}
public class Base
{
public string Name { get; set; }
}
public class Derived : Base
{
public string AdditionalProperty { get; set; }
}
We can then initalize our object like this:
var derived = new Derived()
{
Name = "DerivedFoo",
AdditionalProperty = "Bar"
};
var _base = new Base()
{
Name = "BaseFoo"
};
var x = new Item()
{
ID = Utils.TryCast<int>("please no"),
FooDouble = Utils.TryCast<double>(2),
Base = Utils.TryCast<Base>(derived),
Derived = Utils.TryCast<Derived>(_base),
Bar = "Foo"
};
And we neatly log any errors that might occur when casting:
I'm working with C#. I have a Employee class and I'm getting employee data from a URL then I created a list named EmpList in another class which is being populated with that information. I'm not getting the location of each employee so I want to hard code the location by making a set location function in Employee class.
The name 'EmpList' does not exist in the current context.
I've tried to make setLocation function in CreateEmpList function and I got no error but location was empty.
I know I'm probably doing something silly but I really need some help here. I really appreciate that.
Thankyou.
This is my employee class.
public class Employee
{
public string Name { get; set; }
public string Email { get; set; }
public Guid ID { get; set; }
public string Location { get; set; }
public void SetLocation()
{
foreach (var item in EmpList) // I'm getting error here
{
if (item.Email == "abc#gmail.com")
{
item.Location = "US";
}
}
And here I'm populating the list in another class.
private List<Employee> EmpList = null;
private void CreateEmpList(SPHttpClient client)
{
List<Employee> SortedList = new List<Employee>();
JObject jsondata = client.ExecuteJson(UriResources);
string strjsondata = jsondata.First.First.First.First.ToString();
JArray jsonArray = JArray.Parse(strjsondata);
foreach (var item in jsonArray) // Creating master resources list
{
ResourcesExcemptList.ForEach(i => i.ToLower());
if(!ResourcesExcemptList.Contains(item["ResourceEmailAddress"].
ToString().ToLower()))
{
if (Boolean.Parse(item["ResourceIsActive"].ToString()))
{
Employee emp = new Employee();
emp.ID = (Guid)item["ResourceId"];
emp.Email = item["ResourceEmailAddress"].ToString();
emp.Name = item["ResourceName"].ToString();
emp.Practice = item["ResourceGroup"].ToString();
emp.ApproverID =
(Guid)item["ResourceTimesheetManageId"];
SortedList.Add(emp);
}
}
}
EmpList= SortedList.OrderBy(o => o.Name).ToList();
//private void setLocation(){ }
}
The direct answer to your question
The main issue here is that you're not understanding how object oriented code works. You're not using this, and you seem to be confused when the class method will be executed and what that means.
Oddly, when in a class method, you still expect that you need to look through the list to find the correct object. That's the opposite of how you should approach it.
When an object's class method is being executed, you obviously already have found the object whose method you want to call. Because otherwise you wouldn't have been able to call that object's class method.
So what you need to do here is to iterate over the list before you call the object's class method, not after. Your Employee class:
public void SetLocation()
{
this.Location = "US";
}
And then:
private void CreateEmpList(SPHttpClient client)
{
// the rest of the code
EmpList = SortedList.OrderBy(o => o.Name).ToList();
foreach(var employee in EmpList)
{
employee.SetLocation();
}
}
Footnote
Your question shows a basic confusion on OOP principles, but the code itself shows a different level of grasp on OOP principles. I suspect that you didn't write this code yourself, but a colleague did.
I'm mentioning this because I noticed the comment in your example code:
//private void setLocation(){ }
Notice how its signature is that of a method definition, not that of a method call!
What I think has happened is that your colleague annotated the code and placed a reminder for you to create a method, and you've ended up implementing this method in the Employee class instead of in the other class (the one with the CreateEmpList method in it).
Creating the method in the other class makes a lot more sense than putting it in the Employee class. Something along the lines of:
public void SetLocation(Employee employee)
{
employee.Location = "US";
}
One possible solution, based on my comments:
Declare EmpList as:
public List<Employee> EmpList { get; private set;}
Then in your Employee class:
public void SetLocation()
{
var otherClassObj = new otherClassObj(); // Or perhaps some other way of getting the object of the other class.
otherClassObj.CreateEmpList(client); // You may have to change this.
foreach (var item in otherClassObj.EmpList)
{
if (item.Email == "abc#gmail.com")
{
item.Location = "US";
}
}
}
If your main concern is set location value and if empty then set hardcode value then consider this solution:
private string _location;
public string Location
{
get { return _location; }
set
{
if (string.IsNullOrEmpty(value))
{
_location = "US";
}
else
{
_location = value;
}
}
}
To answer your question: public void SetLocation(List<Employee> EmpList) allows the code inside SetLocation() to access the list object (passed by reference) but I doubt this is what you really want to do. (No offense;-)
Your logic isn't clear but surely within CreateEmpList(),
emp.Email = ...
if (emp.Email...) emp.Location = "..."
or within Employee, something like
public string Email { get {} set { Email = value; if (value...) Location = "..."; } }
I need to determine which object my code is working with at a certain point and write out only the properties specific to that class. I cannot figure out how to do it. I was told I can do it, but I cannot figure it out. Can someone please show me how to determine which object I am working with and write the properties specific to that class only?
I've looked at other questions asked, but am not smart enough to make it fit my example.
Below, I've re-created an example of the code I am working with. I can see all the code, but I am allowed to only work in one method (for this example called "MethodIAmWorkingIn"). Only modifications I am allowed to make are in that method.
public class Program
{
static void Main(string[] args)
{
TestDetailsAndResultsContainer container = new TestDetailsAndResultsContainer();
DerivedClass1 derivedClass1 = new DerivedClass1();
derivedClass1.DerivedClass1Prop1 = "DerivedClass1Prop1";
derivedClass1.DerivedClass1Prop2 = "DerivedClass1Prop2";
DerivedClass2 derivedClass2 = new DerivedClass2();
derivedClass2.DerivedClass2Prop1 = "DerivedClass2Prop1";
derivedClass2.DerivedClass2Prop2 = "DerivedClass2Prop2";
container.TestDetails.Add(derivedClass1);
container.TestDetails.Add(derivedClass2);
TestResult testResult = new TestResult();
testResult.TestResultProp1 = "TestResultProp1";
testResult.TestResultProp2 = "TestResultProp2";
container.Data.Add(testResult);
Program p = new Program();
p.MethodIAmWorkingIn(container);
}
private void MethodIAmWorkingIn(TestDetailsAndResultsContainer container)
{
// I need to see if the container variable holds a DerivedClass1 or DerivedClass2 object.
foreach (var result in container.TestDetails)
{
var classINeedToDetermine = container.TestDetails.FirstOrDefault(m => m.TestDetailsProp1 == result.TestDetailsProp1);
if (classINeedToDetermine is DerivedClass1)
{
classINeedToDetermine = result as DerivedClass1;
}
else if (classINeedToDetermine is DerivedClass2)
{
classINeedToDetermine = result as DerivedClass2;
}
// Now I need to use the classINeedToDetermine object and write its specific properties.
// ???????????????????? I am stuck at this point ??????????????????
// I need to write one or the other below. Can this be done?
// If it is DerivedClass1, I need to write out those properties only.
Console.WriteLine(classINeedToDetermine.DerivedClass1Prop1);
Console.WriteLine(classINeedToDetermine.DerivedClass1Prop2);
// OR
// If it is DerivedClass2, I need to write out those properties only.
Console.WriteLine(classINeedToDetermine.DerivedClass2Prop1);
Console.WriteLine(classINeedToDetermine.DerivedClass2Prop2);
}
}
}
public class TestDetailsAndResultsContainer
{
public TestDetailsAndResultsContainer()
{
this.Data = new List<TestResult>();
this.TestDetails = new List<TestDetails>();
}
public List<TestDetails> TestDetails { get; set; }
public List<TestResult> Data { get; set; }
}
public abstract class TestDetails
{
public string TestDetailsProp1 { get; set; }
public string TestDetailsProp2 { get; set; }
}
public class TestResult
{
public string TestResultProp1 { get; set; }
public string TestResultProp2 { get; set; }
}
public class DerivedClass1 : TestDetails
{
public string DerivedClass1Prop1 { get; set; }
public string DerivedClass1Prop2 { get; set; }
}
public class DerivedClass2 : TestDetails
{
public string DerivedClass2Prop1 { get; set; }
public string DerivedClass2Prop2 { get; set; }
}
The as keyword does not do what you think it does.
Your classINeedToDetermine is a variable of type TestDetails. You can assign a subclass instance to it, but you still cannot access that subclasses specific properties via that variable.
You just need some scope:
if (classINeedToDetermine is DerivedClass1)
{
var derived1 = (DerivedClass1)result;
Console.WriteLine(derived1.DerivedClass1Prop1);
// etc
}
else if (classINeedToDetermine is DerivedClass2)
{
var derived2 = (DerivedClass2)result;
Console.WriteLine(derived2.DerivedClass2Prop1);
// etc
}
This kind of thing is not fun to maintain though.
Another way of doing it would be to use polymorphism: Your TestDetails class could define an abstract method called PrintProperties, and all your subclasses could implement it.
Then you just have to call PrintProperties on every object, without worrying about which subclass they are.
I'm not completely sure on what objects mean what here, but it should be something like this:
foreach(var v in result.GetType().GetProperties())
{
if(v.DeclaringType == result.GetType())
{
Console.WriteLine(v.GetValue(result));
}
}
Again, I wasn't totally clear on your usage of classINeedToDetermine versus result, but you can change those as you see so fit. I chose result as my example since classINeedToDetermine was null by that part of your code.
And by the way, this section of your code is redundant. It should be removed for clarity and efficiency.
if (classINeedToDetermine is DerivedClass1)
{
classINeedToDetermine = result as DerivedClass1;
}
else if (classINeedToDetermine is DerivedClass2)
{
classINeedToDetermine = result as DerivedClass2;
}
Edit:
On the other hand, if performance is more important to you than being scalable (read: if you know or have control over all the classes you'll be dealing with), you could use this is section to do something less, I hate to use this word for this, "generic."
if (classINeedToDetermine is DerivedClass1)
{
var typed = (DerivedClass1)result;
Console.WriteLine(typed.DerivedClass1Prop1);
Console.WriteLine(typed.DerivedClass1Prop2);
}
else if (classINeedToDetermine is DerivedClass2)
{
var typed = (DerivedClass2)result;
Console.WriteLine(typed.DerivedClass2Prop1);
Console.WriteLine(typed.DerivedClass2Prop2);
}
You can use Type.GetProperties to get all Properties for your class. Then you need to get the MethodInfo for the Get method via GetMethod.
Once you have the MethodInfo you can call Invoke, passing in your Derived Class. You can write then write the result to the Console.
I'm basically trying to create a class that holds all the session information, then set and get it at will.
here is my call Session["SessionInformation"] = new SessionVar.UserSession();
and here is that class
public static class SessionVar
{
public class UserSession
{
public string FullName
{
get;
set;
}
public string HomeURL
{
get;
set;
}
public bool ValidUser
{
get;
set;
}
public int CountID
{
get;
set;
}
}
}
Lets say in this example I have a comboBox called CountID_ComboBox and on SelectedIndexChanged I want to set the users specific Session["SessionInformation"] CountID to the value of the combobox. How is that done?
protected void CountID_ComboBox_SelectedIndexChanged(object sender, Telerik.Web.UI.RadComboBoxSelectedIndexChangedEventArgs e)
{
//set the session variable here
}
Also, is there a way to foreach loop the strings in the class. Basically I want to see if any of those variables in that class is null.
So you've created this strongly typed UserSession class to handle your session variables. That's nice, specially if you have a big project, with lots of forms and (junior) developers.
You already know the most important part: for each new session, we'll have one, and only one UserSession object.
Now, let's move on to the part where you actually use it. You can retrieve the object's reference using ((SessionVar.UserSession)Session["SessionInformation"]). Let's dive into it:
Session["something"] returns an object
You want your UserSession object
We cast it using ((SessionVar.UserSession)Session["SessionInformation"]) and your done!
Now, let's say that, later on, you decide to move that object from the session to the viewstate (I'm not saying that this is a good idea, mind you). If you have that code scattered around your project, then it'll be a pain to manage that change.
So, the idea is to have a base page, from which all your pages will inherit. Something like:
public class BasePage : System.Web.UI.Page
{
...
}
And you place the code to retrieve your UserSession there, like:
public class BasePage : System.Web.UI.Page
{
public UserSession CurrentUserSession
{
get
{
UserSession userSession = null;
if (Session["UserSession"] == null)
{
userSession = new UserSession();
Session["UserSession"] = userSession;
}
else
userSession = (UserSession)Session["UserSession"];
return userSession;
}
private set { }
}
}
Bonus: note that, on the code above, I'm suggesting a way to ensure that you get one and only one object for the current user.
Finally, in order to get a list of the string properties that are empty, you can use the following method (place it inside UserSession):
public List<string> GetEmptyStringAttributes()
{
List<string> emptyStringAttributes = new List<string>();
Type type = this.GetType();
foreach (System.Reflection.PropertyInfo property in type.GetProperties())
{
if (property.PropertyType == typeof(String))
{
string value = property.GetValue(this) as string;
if (string.IsNullOrWhiteSpace(value))
emptyStringAttributes.Add(property.Name);
}
}
return emptyStringAttributes;
}
}
In case you can't find the combo box from your code behind, I'll use sender just to be sure we have the correct control.
var cBox = (RadComboBox)sender;
(SessionVar.UserSession)Session["SessionInformation"].CountID = cBox.SelectedValue;
It seems like the root of your question is actually about casting.
I've got a question about getting the values from a constructor in a generic way.
namespace myTestNamespace
{
Public Class myTestClass()
{
Public myTestClass(int myInt,bool myBool, double myDouble)
{
//do / set something
}
Public myTestClass(int myInt,bool myBool)
{
//do / set something
}
}
}
Using (what you need);
Using myTestNamespace;
namespace MyIWannaLookForTheParametersName
{
Public Class MyLookUpClass()
{
Public void DoSomething()
{
List<object> myList = new List<object>();
myTestClass _ myTestClass = new myTestClass(1,true,2.5);
object mySaveObject = myTestClass;
mylist.Add(mySaveObject);
//how do I get the info from the right constructor
//(I used the one with 3 parameters_
//what was the value of myInt, myBool and myDouble
//how can I make it generic enough, so it will work with other classes with
// different constructors ass well?
}
}
}
Questions about intent aside, there's no generic way for you to do this. Information about what methods have been called and what values were supplied is not saved automatically. You are, of course, perfectly able to keep track of these things yourself, but you would have to write each class to do this explicitly.
Doing this in a generic way is asking for trouble. What if I did this?
public class Foo
{
public string Name { get; set; }
}
public class Bar
{
public Bar(Foo foo)
{
// ...
}
}
Then suppose I called it in this way:
Foo f = new Foo();
f.Name = "Jim";
Bar b = new Bar(f);
f.Name = "Bob";
Now, if such a generic system existed, what would be the value of foo for the Bar constructor? Either it reports "Bob" (which is what the value for Name is on the instance of Foo that was supplied), or it reports "Jim", meaning that the runtime or library would essentially have to be smart enough to make a deep copy of the object so that the state is not changed.
The bottom line is this: if you need access to the parameters passed to the constructor (or any other function), you'll have to store them somewhere explicitly.
You can't get thevalues from the constructor. You need to first place them in a property or a field within your class. The example you provided is a poor use of generics. You wouldbe better off placing the constructor values into properties and creating an interface with those properties.
I got what I needed with this method:
private static ParameterSettings[] GetListOfParametersFromIndicator(object indicatorClass, int loopId, myEnums.ParaOrResult paraOrResult)
{
return (from prop in indicatorClass.GetType().GetProperties()
let loopID = loopId
let Indicator = indicatorClass.GetType().Name
let value = (object)prop.GetValue(indicatorClass, null)
where prop.Name.Contains("_Constr_")
select new ParameterSettings { ParaOrResult=paraOrResult, LoopID= loopId, Indicator= Indicator, ParaName= prop.Name, Value= value }).ToArray();
}
where ParameterSettings is:
public struct ParameterSettings
{
public myEnums.ParaOrResult ParaOrResult { get; set; }
public int LoopID { get; set; }
public string Indicator { get; set; }
public string ParaName { get; set; }
public object Value { get; set; }
}
This info is ok for me. Thanks for the replies.
Regards,
Matthijs