How to get AllJoyn byte[] property - c#

I have an AllJoyn property like this
<property name="DeviceAddresses" type="ay" access="read">
I a Windows 10 UWP app when I try to read it - I get success - but I don't know how to get out the value from the result
Code looks like this:
var vProperty = pInterface.GetProperty(propertyName);
if (vProperty == null) return null;
var result = await vProperty.ReadValueAsync();
if (result.Status.IsSuccess)
{
if (vProperty.TypeInfo.Type == TypeId.Uint8Array)
{
byte[] Erg = result.Value ???
}
}
The property value is created via
object o = Windows.Foundation.PropertyValue.CreateUInt8Array(value);
But I found no way (casting or so) the get the bytes out.

I use DeviceProviders to access AllJoyn methods. It uses
IAsyncOperation<InvokeMethodResult> InvokeAsync(IList<object> #params);
to get the server response. It looks similar to what your ReadValueAsync() returns. But not quite the same. This is how I access the bytes.
InvokeMethodResult result = await MyAllJoynMethod.InvokeAsync(new List<object> { "parameter", 2 });
if (result.Status.IsSuccess)
{
var resultList = result.Values as IList<object>;
foreach (var resultListItem in resultList)
{
var pairs = resultListItem as IList<KeyValuePair<object, object>>;
foreach (var pair in pairs)
{
var key = pair.Key as string; //<- type string taken from MyAllJoynMethod definition
var variant = pair.Value as AllJoynMessageArgVariant;//<- type AllJoynMessageArgVariant taken from MyAllJoynMethod definition (variant)
if (variant.TypeDefinition.Type == TypeId.Uint8Array)
{
var array8 = j as IList<object>;
foreach (byte b in array8)
{
// do something with b
}
}
}
}
}
EDIT: If you do not want to program it yourself you can use OpenAlljoynExplorer. Not sure if byte arrays are actually supported, yet.

Related

Accessing elements of an Array (of any element type) from an object

I use management to access devices properties and I wrote a code below to create an array of dictionaries. my application show properties in a listview control; so I need to convert all properties value to simple string
Dictionary<string,string>[] getInfo(string k) {
// using `k` as management-key
var mos = new ManagementObjectSearcher($"select * from {k}");
var devices = new List<Dictionary<string, string>>();
var mosc = mos.Get(); // mosc is a collection of all devices with same key
foreach (var device in mosc) {
var properties = new Dictionary<string, string>();
foreach (var p in device.Properties) {
if (p.Value != null) {
if (p.IsArray) {
// I have problem in here
// my application must convert p.value to string
var collection = (IEnumerable<object>)p.Value
properties[p.Name] = string.Join(", ", collection.Select(x=>x.ToString()));
} else
properties[p.Name] = p.Value.ToString();
} else properties[p.Name] = "";
}
devices.Add(properties);
}
return devices.ToArray();
}
p.Value type is object but sometimes it contain an array like UInt[] or String[], I found part of code from stackoverflow but it didn't help me and it say:
System.InvalidCastException: 'Unable to cast object of type 'System.UInt16[]' to type 'System.Collections.Generic.IEnumerable`1[System.Object]'.'
I tried code below too, but it say same thing:
int[] array = new int[] { 0, 1, 2 }; // <- I haven't access to `array` in my main problem
object obj=array;
// I only can use `obj`
// `obj` is similar to `p.Value` here
IEnumerable<object> collection = (IEnumerable<object>)obj; // <- this line throws exception!
string output=string.join(", ",collection.Select(x=>x.ToString()));
I also tried this codes:
var collection= p.Value as IEnumerable;
// ^ found this line from stackoverflow
// says: Using the generic type 'IEnumerable<T>' requires 1 type arguments
var collection= p.Value as IEnumerable<object>
// `collection` will be null
var collection= (object[]) p.Value
// says: Unable to cast object of type 'System.Int32[]' (or some something like String[]) to type 'System.Object[]'.
IEnumerable<T> is covariant in T so this would be allowed:
IEnumerable<Giraffes> giraffes = ....
var animals = (IEnumerable<Animal>)giraffes;
So then, why does this not work as well?
var array = new[] { 1, 2, 3 };
var objects = (IEnumerable<object>)array; //will not compile
int extends object, right?
Well, the reason is that type variance in C# is only allowed between reference types; the rule is that variance must preverse identity, and there is no way to cast a value type preserving identity in C#; only reference types can and those types of conversion are called reference conversions:
var animal = (Animal)giraffe;
var o = (object)"Hello";
IFish fish = cod;
//etc.
The bits that make up the object dont change, only the type of the refernece changes, hence the name of the conversion. Note that in the very first example, animals and giraffes are the same object, object.ReferenceEquals(animals, giraffes) will return true; we've only changed the type of the variable referencing it.
In your case, to obtain an IEnumerable<object> from an IEnumerable<someValueType>, you'll have to enumerate and box each item creating a new enumerable of the desired type. In order to do so, you can use the extension method Enumerable.Cast<T>():
IEnumerable<object> objects = array.Cast<object>();
Or do the projection yourself:
IEnumerable<object> objects = array.Select(i => (object)i);
second code:
int[] array = new int[] { 0, 1, 2 };
object obj=array;
var obj_array=(Array)obj;
IEnumerable<object> collection = obj_array.Cast<object>();
string output=string.join(", ",collection.Select(x=>x.ToString()));
so main code will be:
Dictionary<string,string>[] getInfo(string k) {
// using `k` as management-key
var mos = new ManagementObjectSearcher($"select * from {k}");
var devices = new List<Dictionary<string, string>>();
var mosc = mos.Get(); // mosc is a collection of all devices with same key
foreach (var device in mosc) {
var properties = new Dictionary<string, string>();
foreach (var p in device.Properties) {
if (p.Value != null) {
if (p.IsArray) {
var array = (Array)p.Value;
var collection = array.Cast<object>();
properties[p.Name] = string.Join(", ", collection.Select(x=>x.ToString()));
} else
properties[p.Name] = p.Value.ToString();
} else properties[p.Name] = "";
}
devices.Add(properties);
}
return devices.ToArray();
}

Using foreach statement on variables of type 'Task<List<SharepointDTO.RootObject>>

I am trying to call the Sharepoint API multiple times in a C# application and storing the returned results in to a List like below
private async Task<List<sDTO.RootObject>> getfromSharepoint()
{
List<SharepointDTO.RootObject> returnObj = new List<SharepointDTO.RootObject>();
var result = new UpdateCoreStrains.SharepointDTO.RootObject();
......
// Calling GET Sharepoint Site
try
{
for (int i = 0; i < 10000; i = i + 5000)
{
SP_StrainCodes = "GetByTitle('S%20Codes')/items?$skiptoken=Paged=TRUE%26p_ID=" + i + "&$top=1";
core_URL = BaseURL_SP + SP_StrainCodes;
var response = client_sharePoint.GetAsync(core_URL).Result;
var responsedata = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<sDTO.RootObject>(responsedata);
if (result.d.Next == null)
continue;
}
returnObj.Add(result);
}
return returnObj;
}
Now I am calling getfromSharepoint() in other function and I want to iterate over the List to validate the data
public List<numberList> getListFromSharepoint()
{
List<umberList> nums = new List<numberList>();
try
{
Task<List<sDTO.RootObject>> sharepointList = getfromSharepoint();
foreach(sDTO retSharepointobj in sharepointList)
{
if (retSharepointobj == null ||
retSharepointobj.Id == 0 ||
retSharepointobj.Result.
retSharepointobj.Result == null ||
retSharepointobj.Result.d == null ||
retSharepointobj.Result.d.results == null ||
retSharepointobj.Result.d.results.Count == 0
)
{
return nums; // count = 0, return an empty list
}
But I am getting an error like
foreach statement cannot operate on variables of type 'Task<List<SharepointDTO.RootObject>>' because 'Task<List<SharepointDTO.RootObject>>' does not contain a public definition for 'GetEnumerator' How can I iterate over >
Try to make your getListFromSharepoint method as async.
public async Task<List<numberList>> getListFromSharepoint()
{
List<umberList> nums = new List<numberList>();
try
{
//Here we use an await to get result from getfromSharepoint() method call.
List<sDTO.RootObject> sharepointList = await getfromSharepoint();
foreach (sDTO retSharepointobj in sharepointList)
{
//your rest of code is same here
}
Edit:
And from other function call getListFromSharepoint method as
List<numberList> result = await getListFromSharepoint();
OR
You could simply use Result of getfromSharepoint.
List<sDTO.RootObject> sharepointList = await getfromSharepoint().Result;
Here you are trying to iterate over items of sharepointList which is of type Task which does not contain a public definition for 'GetEnumerator'(As the error message stated). But you can Iterate over the Result of Task since its a collection of RootObject. If you are looking for looping through List<sDTO.RootObject> of sharepointList you should use :
foreach (sDTO.RootObject retSharepointobj in sharepointList.Result)
{
// here each retSharepointobj of type RootObject
// code here
}
Ths: Task<List<sDTO.RootObject>> sharepointList = getfromSharepoint(); is calling an async method, which doesn't return immediately. Your code should look something like so:
List<sDTO.RootObject> sharepointList = getfromSharepoint().Result;

Converting/handling returned IList object

I'm having issues extracting values from a returned IList and populating a combobox in windows.forms. All items in the combobox are listed as System.object.
I have done some testing;
var retList = Services.Get<IWarehouseInfo>().ExecuteSPArray("sp_executesql", dict); <-- method that returns some values.
//Tries to extract value from retlist/which is a IList<object[]> collection.
var strList = (from o in retList select o.ToString()).ToList();
var strList2 = retList.OfType<string>().ToList();
var strList3 = retList.Cast<string>();
var strList4 = retList.Where(x => x != null).Select(x => x.ToString()).ToList(); //All these seem to result in system object.
var bub = strList.ElementAt(2).ToString();
var bob = strList4.ElementAt(2).ToString();
var kupa = strList.ToArray();
var kupo = kupa[2].ToString();
All these fail to extract anything useful.
I thank you all for any beeps given. My mistake was that I thought
that the returned values were in a list of objects. But the result was
an IEnumerable, so I did not check the correct vector.
I added an method extracting the values and returning it in desired format, in this case string.
private static List<string> ToListString(IEnumerable<object[]> inparam)
{
var custNums = new List<string>();
foreach (var row in inparam)
{
if (row[0] != null && row[0] != DBNull.Value)
custNums.Add(row[0].ToString());
}
return custNums;
}

Finding all identifiers containing part of the token

I know I can get a string from resources using
Resources.GetIdentifier(token, "string", ctx.ApplicationContext.PackageName)
(sorry, this is in C#, it's part of a Xamarin.Android project).
I know that if my elements are called foo_1, foo_2, foo_3, then I can iterate and grab the strings using something like
var myList = new List<string>();
for(var i = 0; i < 4; ++i)
{
var id = AppContent.GetIdentifier(token + i.ToString(), "string", "package_name");
if (id != 0)
myList.Add(AppContext.GetString(id));
}
My issue is that my token names all begin with "posn." (the posn can denote the position of anything, so you can have "posn.left_arm" and "posn.brokenose"). I want to be able to add to the list of posn elements, so I can't really store a list of the parts after the period. I can't use a string-array for this either (specific reason means I can't do this).
Is there a way that I can use something akin to "posn.*" in the getidentifer call to return the ids?
You can use some reflection foo to get what you want. It is not pretty at all but it works. The reflection stuff is based on https://gist.github.com/atsushieno/4e66da6e492dfb6c1dd0
private List<string> _stringNames;
private IEnumerable<int> GetIdentifiers(string contains)
{
if (_stringNames == null)
{
var eass = Assembly.GetExecutingAssembly();
Func<Assembly, Type> f = ass =>
ass.GetCustomAttributes(typeof(ResourceDesignerAttribute), true)
.OfType<ResourceDesignerAttribute>()
.Where(ca => ca.IsApplication)
.Select(ca => ass.GetType(ca.FullName))
.FirstOrDefault(ty => ty != null);
var t = f(eass) ??
AppDomain.CurrentDomain.GetAssemblies().Select(ass => f(ass)).FirstOrDefault(ty => ty != null);
if (t != null)
{
var strings = t.GetNestedTypes().FirstOrDefault(n => n.Name == "String");
if (strings != null)
{
var fields = strings.GetFields();
_stringNames = new List<string>();
foreach (var field in fields)
{
_stringNames.Add(field.Name);
}
}
}
}
if (_stringNames != null)
{
var names = _stringNames.Where(s => s.Contains(contains));
foreach (var name in names)
{
yield return Resources.GetIdentifier(name, "string", ComponentName.PackageName);
}
}
}
Then somewhere in your Activity you could do:
var ids = GetIdentifiers("action").ToList();
That will give you all the String Resources, which contain the string action.

C#. Set a member object value using reflection

I need your help with the following code below. Basically I have a class called "Job" which has some public fields. I'm passing to my method "ApplyFilter" two parameters "job_in" and "job_filters". First parameter contains actual data, and the second one has instructions (if any). I need to iterate through "job_in" object, read it's data, apply any instructions by reading "job_filters", modify data (if needed) and return it in a new "job_out" object. Everything works fine till i need to store my data in "job_out" object:
public class Job
{
public string job_id = "";
public string description = "";
public string address = "";
public string details = "";
}
...
private Job ApplyFilters(Job job_in, Job job_filters)
{
Type type = typeof(Job);
Job job_out = new Job();
FieldInfo[] fields = type.GetFields();
// iterate through all fields of Job class
for (int i = 0; i < fields.Length; i++)
{
List<string> filterslist = new List<string>();
string filters = (string)fields[i].GetValue(job_filters);
// if job_filters contaisn magic word "$" for the field, then do something with a field, otherwise just copy it to job_out object
if (filters.Contains("$"))
{
filters = filters.Substring(filters.IndexOf("$") + 1, filters.Length - filters.IndexOf("$") - 1);
// MessageBox.Show(filters);
// do sothing useful...
}
else
{
// this is my current field value
var str_value = fields[i].GetValue(job_in);
// this is my current filed name
var field_name = fields[i].Name;
// I got stuck here :(
// I need to save (copy) data "str_value" from job_in.field_name to job_out.field_name
// HELP!!!
}
}
return job_out;
}
Please help. I've seen a few samples by using properties, but i'm pretty sure it is possible to do the same with fields as well. Thanks!
Try this
public static void MapAllFields(object source, object dst)
{
System.Reflection.FieldInfo[] ps = source.GetType().GetFields();
foreach (var item in ps)
{
var o = item.GetValue(source);
var p = dst.GetType().GetField(item.Name);
if (p != null)
{
Type t = Nullable.GetUnderlyingType(p.FieldType) ?? p.FieldType;
object safeValue = (o == null) ? null : Convert.ChangeType(o, t);
p.SetValue(dst, safeValue);
}
}
}
fields[i].SetValue(job_out, str_value);

Categories