CipherIS
asked on
C# Get Values from object sender
Or you can use safe casting
Normally you should do NULL checking after casting like this but in the case where you're casting a sender object you're pretty much guaranteed that the sender is an object and it is of the type you expect. If it isn't someone up the line made a pretty major programming mistake.
You can also significantly shorten the above line by including a using statement to import the namespace. It'll probably be something like this:
(sender as Aimetis.Symphony.SDK.NotificationMonitors.CameraMessageMonitor).value
where "value" is the name of the property you're trying to access.Normally you should do NULL checking after casting like this but in the case where you're casting a sender object you're pretty much guaranteed that the sender is an object and it is of the type you expect. If it isn't someone up the line made a pretty major programming mistake.
You can also significantly shorten the above line by including a using statement to import the namespace. It'll probably be something like this:
using Aimetis.Symphony.SDK.NotificationMonitors;
Then your cast is simply(sender as CameraMessageMonitor).value
ASKER
No error with the casting but the nothing showing up with intellisense and seem not to be getting any thing.
If you cast like I did above you should get Intellisense. Make sure you use the parentheses.
ASKER
(sender as Aimetis.Symphony.SDK.Notif icationMon itors.Came raMessageM onitor).va lue
Receive error - CameraMessageMonitor does not contain a definition 'value' and no extension method 'value' accepting first argument of type CameraMessageMonitor could be found.
Receive error - CameraMessageMonitor does not contain a definition 'value' and no extension method 'value' accepting first argument of type CameraMessageMonitor could be found.
As I said above, replace "value" with whatever property you want to access. You should get intellisense after you type the last dot "." following the close parenthesis.
ASKER
Found the value. Receiving the below error.
Object2.jpg
Object2.jpg
@Russ Suter
That approach isn't any safer than a direct cast.
That approach isn't any safer than a direct cast.
ASKER
var s = (CameraMessageMonitor)sender;
Above code worked. I'm looking at my watch window and it is returning the below values. How do I get the values of m_source and also AlarmDataTable and the sub values in there?
Thanks
Object3.jpg
@käµfm³d 👽
Safe cast will return a null value if the cast is invalid. You'll get an exception the other way. Which means it is safer. Exceptions are something to be avoided whenever possible.
Safe cast will return a null value if the cast is invalid. You'll get an exception the other way. Which means it is safer. Exceptions are something to be avoided whenever possible.
Calling .Vaue at the end of the cast as you have written it will most certainly result in a NullReferenceException if the cast fails, hence my comment. If you were to instead do the check for null, as you mentioned in comment, then it would be safer.
This is a technique I use frequently when working inside event handlers. The only two ways that cast could result in an exception are if I cast to the wrong type or the person who wrote the underlying code wrote the event handler wrong. Either way, an exception means bad code. Checking for null when casting the sender argument inside an event handler is unnecessary and wasteful code.
ASKER
Ok, below code returned the values from the sender object.
I included an image above "object3" which shows what is stored.
I am trying to get the values in "s".
I tried
But the error I receive is "Could not find an implementation of the query pattern for source type 'CameraMessageMonitor'. 'Select' not found."
When I add "s" to my watch it provides all the values.
var s = (CameraMessageMonitor)sender;
I included an image above "object3" which shows what is stored.
I am trying to get the values in "s".
I tried
var x = (from temp in s select new {}).ToList();
But the error I receive is "Could not find an implementation of the query pattern for source type 'CameraMessageMonitor'. 'Select' not found."
When I add "s" to my watch it provides all the values.
You cannot LINQ against a control**...that doesn't make sense. You LINQ over a collection (i.e. something that implements IEnumerable).
** Unless, of course, some control happens to implement IEnumerable, which is technically possible.
** Unless, of course, some control happens to implement IEnumerable, which is technically possible.
ASKER
Ok, so how do I get the values?
You want the same "values" that you see in the Watch (i.e. the object/control's properties)?
ASKER
I'm trying to get to those values. When I type s. intellisense gives me below.
object4.jpg
object4.jpg
You would need Reflection, then.
e.g.
This is a crude example. You'll probably have to tweak it.
e.g.
foreach (System.Reflection.PropertyInfo property in sender.GetType().GetProperties(System.Reflection.BindingFlags.Instance))
{
string name = property.Name;
object value = property.GetValue(sender);
Console.WriteLine("{0} - {1}", name, value.ToString());
}
This is a crude example. You'll probably have to tweak it.
ASKER
It's not going inside for loop.
The foreach loop in the above wraps the Reflection logic. Maybe I'm misunderstanding what you're trying to do, but based on what I read above you want the value of each property in the object--dynamically--and if so, then you use Reflection. My foreach loop just iterates over the object's properties.
ASKER
Yes, that is what I want but it is not going inside the loop.
Ah, my mistake. I think it needs another BindingFlag:
foreach (System.Reflection.PropertyInfo property in sender.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public))
ASKER
Still not dropping inside for loop.
ASKER
I tried this and it is still not going inside the for loop.
foreach (PropertyInfo property in sender.GetType().GetProperties(BindingFlags.CreateInstance |
BindingFlags.DeclaredOnly |
BindingFlags.Default |
BindingFlags.ExactBinding |
BindingFlags.FlattenHierarchy |
BindingFlags.GetField |
BindingFlags.GetProperty |
BindingFlags.IgnoreCase |
BindingFlags.IgnoreReturn |
BindingFlags.Instance |
BindingFlags.InvokeMethod |
BindingFlags.NonPublic |
BindingFlags.OptionalParamBinding |
BindingFlags.Public |
BindingFlags.PutDispProperty |
BindingFlags.PutRefDispProperty |
BindingFlags.SetField |
BindingFlags.Static |
BindingFlags.SuppressChangeType
))
{
string name = property.Name;
object value = property.GetValue(sender);
Console.WriteLine("{0} - {1}", name, value.ToString());
}
ASKER
ReflectedType: '((System.RuntimeType)(s.G etType())) .Reflected Type' threw an exception of type 'System.NotSupportedExcept ion'
ASKER
I put the code for the button and it works for the button but not for the CameraMessageMonitor. Any other way to get the values?
What property are you wanting to get? The binding flags by default provide instance and public properties. If you want the private and/or protected properties you will have to add BindingFlags.NonPublic; e.g. -
using System;
using System.Linq;
using System.Reflection;
namespace EE_Q28924773
{
class Program
{
static void Main(string[] args)
{
SomeClass _someClass = new SomeClass();
var _noFlags = (from prop in _someClass.GetType().GetProperties() select new { Name = prop.Name, Value = prop.GetValue(_someClass, null) });
var _public = (from prop in _someClass.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public) select new { Name = prop.Name, Value = prop.GetValue(_someClass, null) });
var _nonPublic = (from prop in _someClass.GetType().GetProperties(BindingFlags.Instance | BindingFlags.NonPublic) select new { Name = prop.Name, Value = prop.GetValue(_someClass, null) });
Console.WriteLine("NoFlag Properties");
foreach (var item in _noFlags)
Console.WriteLine(item);
Console.WriteLine();
Console.WriteLine("Public Properties");
foreach (var item in _public)
Console.WriteLine(item);
Console.WriteLine();
Console.WriteLine("NonPublic Properties");
foreach (var item in _nonPublic)
Console.WriteLine(item);
Console.ReadLine();
}
}
class SomeClass
{
string _privateStringField = "Private Field";
protected internal string _protectedInternalStringField = "Protected Internal Field";
internal string _internalStringField = "Internal Field";
protected string _protectedStringField = "Protected Field";
public string _publicStringField = "Public Field";
string PrivateStringProperty
{
get { return _privateStringField; }
set { _privateStringField = value; }
}
protected internal string ProtectedInternalStringProperty
{
get { return _protectedInternalStringField; }
set { _protectedInternalStringField = value; }
}
internal string InternalStringProperty
{
get { return _internalStringField; }
set { _internalStringField = value; }
}
protected string ProtectedStringProperty
{
get { return _protectedStringField; }
set { _protectedStringField = value; }
}
public string PublicStringProperty
{
get { return _publicStringField; }
set { _publicStringField = value; }
}
}
}
Which produces the following output -You can combine binding flags as well since it is a flag based enumeration; e.g. -
using System;
using System.Linq;
using System.Reflection;
namespace EE_Q28924773
{
class Program
{
static void Main(string[] args)
{
SomeClass _someClass = new SomeClass();
var _allProperties = (from prop in _someClass.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) select new { Name = prop.Name, Value = prop.GetValue(_someClass, null) });
Console.WriteLine("All Properties");
foreach (var item in _allProperties)
Console.WriteLine(item);
Console.ReadLine();
}
}
class SomeClass
{
string _privateStringField = "Private Field";
protected internal string _protectedInternalStringField = "Protected Internal Field";
internal string _internalStringField = "Internal Field";
protected string _protectedStringField = "Protected Field";
public string _publicStringField = "Public Field";
string PrivateStringProperty
{
get { return _privateStringField; }
set { _privateStringField = value; }
}
protected internal string ProtectedInternalStringProperty
{
get { return _protectedInternalStringField; }
set { _protectedInternalStringField = value; }
}
internal string InternalStringProperty
{
get { return _internalStringField; }
set { _internalStringField = value; }
}
protected string ProtectedStringProperty
{
get { return _protectedStringField; }
set { _protectedStringField = value; }
}
public string PublicStringProperty
{
get { return _publicStringField; }
set { _publicStringField = value; }
}
}
}
Which produces the following output -If you want fields (because not all fields have properties) then use the GetFields methods with the appropriate binding flags; e.g. -
using System;
using System.Linq;
using System.Reflection;
namespace EE_Q28924773
{
class Program
{
static void Main(string[] args)
{
SomeClass _someClass = new SomeClass();
var _allProperties = (from prop in _someClass.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) select new { Name = prop.Name, Value = prop.GetValue(_someClass, null) });
var _allFields = (from field in _someClass.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) select new { Name = field.Name, Value = field.GetValue(_someClass) });
Console.WriteLine("All Properties");
foreach (var item in _allProperties)
Console.WriteLine(item);
Console.WriteLine();
Console.WriteLine("All Fields");
foreach (var item in _allFields)
Console.WriteLine(item);
Console.ReadLine();
}
}
class SomeClass
{
string _privateStringField = "Private Field";
protected internal string _protectedInternalStringField = "Protected Internal Field";
internal string _internalStringField = "Internal Field";
protected string _protectedStringField = "Protected Field";
public string _publicStringField = "Public Field";
string PrivateStringProperty { get; set; }
protected internal string ProtectedInternalStringProperty { get; set; }
internal string InternalStringProperty { get; set; }
protected string ProtectedStringProperty { get; set; }
public string PublicStringProperty { get; set; }
}
}
Which produces the following output --saige-
Also, heed kaufmeds advice on null checking your values (I did not above).
-saige-
-saige-
ASKER
Yes, and like I said, the code works for the button. I tried it but it is not working for
The code is NOT going inside the "for loop".
I am trying to get the values in the the attached image
Object3.jpg
var s = (CameraMessageMonitor)sender;
foreach (PropertyInfo property in s.GetType().GetProperties(BindingFlags.Instance |
BindingFlags.Public
))
{
string name = property.Name;
object value = (property.GetValue(sender) ?? null).ToString();
Console.WriteLine("{0} - {1}", name, value.ToString());
}
The code is NOT going inside the "for loop".
I am trying to get the values in the the attached image
Object3.jpg
In your image. m_source is a field, not a property. In order to retrieve this, you need to use the GetField or GetFields method. Also, m_source is a protected field, which means that you need to include BindingFlags.NonPublic in your list of BindingFlags parameters.
From there, you can then get the properties (the wrench indicates properties) of m_source by retrieving it's type and using GetProperties.
-saige-
From there, you can then get the properties (the wrench indicates properties) of m_source by retrieving it's type and using GetProperties.
-saige-
ASKER
I tried below
foreach (PropertyInfo property in s.GetType().GetProperties( BindingFla gs.CreateI nstance |
BindingFlags.DeclaredOnly |
BindingFlags.Default |
BindingFlags.ExactBinding |
BindingFlags.FlattenHierar chy |
BindingFlags.GetField |
BindingFlags.GetProperty |
BindingFlags.IgnoreCase |
BindingFlags.IgnoreReturn |
BindingFlags.Instance |
BindingFlags.InvokeMethod |
BindingFlags.NonPublic |
BindingFlags.OptionalParam Binding |
BindingFlags.Public |
BindingFlags.PutDispProper ty |
BindingFlags.PutRefDispPro perty |
BindingFlags.SetField |
BindingFlags.Static |
BindingFlags.SuppressChang eType
))
I added one at a time to see if it would drop inside the for loop and it still did not drop in the for loop.
foreach (PropertyInfo property in s.GetType().GetProperties(
BindingFlags.DeclaredOnly |
BindingFlags.Default |
BindingFlags.ExactBinding |
BindingFlags.FlattenHierar
BindingFlags.GetField |
BindingFlags.GetProperty |
BindingFlags.IgnoreCase |
BindingFlags.IgnoreReturn |
BindingFlags.Instance |
BindingFlags.InvokeMethod |
BindingFlags.NonPublic |
BindingFlags.OptionalParam
BindingFlags.Public |
BindingFlags.PutDispProper
BindingFlags.PutRefDispPro
BindingFlags.SetField |
BindingFlags.Static |
BindingFlags.SuppressChang
))
I added one at a time to see if it would drop inside the for loop and it still did not drop in the for loop.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
GetProperties will only return properties, not fields (you will get the field values from their associated properties if the property defines a get method). If you need the fields, you must use GetFields with the appropriate binding flags. In 99.9% of all cases the following binding flags parameters will suffice:
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static
-saige-
ASKER
I'm walking through it. I am getting the property.name. When I get the value I receive the below error.
'(property.GetValue(s) ?? null).ToString()' threw an exception of type 'System.Reflection.TargetE xception'
Data: {System.Collections.ListDi ctionaryIn ternal}
HResult: -2146232829
HelpLink: null
InnerException: null
Message: "Object does not match target type."
Source: "mscorlib"
StackTrace: " at System.Reflection.RuntimeM ethodInfo. CheckConsi stency(Obj ect target)\r\n at System.Reflection.RuntimeM ethodInfo. InvokeArgu mentsCheck (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)\r\n at System.Reflection.RuntimeM ethodInfo. Invoke(Obj ect obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)\r\n at System.Reflection.RuntimeP ropertyInf o.GetValue (Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)\r\n at System.Reflection.RuntimeP ropertyInf o.GetValue (Object obj, Object[] index)\r\n at System.Reflection.Property Info.GetVa lue(Object obj)"
TargetSite: {Void CheckConsistency(System.Ob ject)}
'(property.GetValue(s) ?? null).ToString()' threw an exception of type 'System.Reflection.TargetE
Data: {System.Collections.ListDi
HResult: -2146232829
HelpLink: null
InnerException: null
Message: "Object does not match target type."
Source: "mscorlib"
StackTrace: " at System.Reflection.RuntimeM
TargetSite: {Void CheckConsistency(System.Ob
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks. That helped a lot.
Line 12 in both offerings should be (the string "null", not the operator):
@it_saige
Good catch. I was hand-coding that one in TextPad, so I didn't catch that bit.
object value = (property.GetValue(m_source) ?? "null").ToString();
@it_saige
Good catch. I was hand-coding that one in TextPad, so I didn't catch that bit.
Open in new window