How to dynamically use getters/setters in Dart - reflection

class User{
String firstName;
String lastName;
String email;
}
I want to be able to get and set one of the fields in user with a dynamically selected symbol or string. For example String value = u[new Symbol("firstName")];
I see that InstanceMirror has a getField method, but it doesn't seem to return the value. All I need is the value.

If you create a symbol with # you need to know the name at compile time.
I got it working this way:
library operator_lib;
import 'dart:mirrors';
void main(List<String> args) {
var x = new X();
var f = new Symbol('firstName');
var r = reflect(x);
print(r.getField(f).reflectee);
r.setField(f, "John");
print(r.getField(f).reflectee);
}
class X {
String firstName = 'Mike';
}

Related

ActiveAndroid NPE from execute

I am following https://github.com/pardom/ActiveAndroid/wiki/Querying-the-database to incorporate activeandroid in my application like so:
#Table(name="Contact")
public class Contact extends Model implements Serializable, Comparable {
public Contact() {
super();
}
public Contact(String id, String n, String c, String p, String addr, String phone,
String fb, String twit, String yt) {
super();
candID = id;
name = n;
chamber = c;
party = p;
address = addr;
phoneNo = phone;
facebook = fb;
twitter = twit;
youtube = yt;
}
public static List<Contact> getCachedContactsByState(String stateAbbr) {
/*return new Select().from(Contact.class).where("state = ?",
stateAbbr).execute();*/
Select s = new Select();
From f = s.from(Contact.class);
f = f.where("state = ?", stateAbbr);
List<Contact> cachedContacts = f.execute();
return cachedContacts;
}
According to my debugger, the f.execute throws a null pointer exception, and f is not null.
just making sure, the tutorial didn't mention needing to install sqlite before using activeandroid, and it said the point of activeandroid was to use objects and their functions to do CRUD on sqlite, so I'm assuming I just needed to follow the tutorial to create and query my sqlite db?
Looks like you've forgotten to call ActiveAndroid.initialize() with a valid Context. See the Getting Started section from the documentation you linked to.

Save and Restore an object to database

Lets say i have an object with this format:
public class ObjectClassSample
{
public string product { set; get; }
public string Description { set; get; }
public int Price { set; get; }
}
Im trying to same this object inside a string field in a record in my database. is it possible to this without converting this to JSON, as i was thinking what is the best way to save and restore this.
One way or another you have to convert that object to a string, I'm unsure why you don't want to use JSON, but to do it without converting to JSON, you could make your own error prone format.
Here is an example of just converting the object to a string, separating each property by a comma.
Some Extension Methods
public static class ObjectSampleExtensions
{
public static ObjectClassSample ToObjectClassSample(this string s)
{
var parts = s.Split(new [] { ','});
return new ObjectClassSample
{
product = parts[0],
Description = parts[1],
Price = int.Parse(parts[2])
};
}
public static string ConvertToString(this ObjectClassSample objectToConvertToString)
{
const string delimiter = ",";
var sb = new StringBuilder();
sb.Append(objectToConvertToString.product);
sb.Append(delimiter);
sb.Append(objectToConvertToString.Description);
sb.Append(delimiter);
sb.Append(objectToConvertToString.Price);
return sb.ToString();
}
}
Then Usage
void Main()
{
var obj = new ObjectClassSample
{
Description = "this is the description",
Price = 3,
product = "my product"
};
var s = obj.ConvertToString();
//you can now save s to the database
Db.Save(s);
//later on pretend you read 's' back from the database
s = Db.ReadAnItem();
var objectFromDb = s.ToObjectClassSample();
}
So yeah, you can serialize the data anyway you want, but I would use a common format: json, xml, csv, whatever.
I wouldn't recommend using the code above, that was just an example to show you can basically do whatever you want to convert it to a string, so long as you can convert it back. Using a json parser would be much easier though.
An example with ServiceStack.Text would look like this
var objToSerialize = new ObjectClassSample(); //fill this with data
string myObjectAsString = objToSerialize.ToJson();
//reading it back from the database
ObjectClassSample myObj = myObjectAsString.FromJson<ObjectClassSample>();
I'm sure newstonsoft.json is similar.
As you can see...much prettier.

Load ProfileBase without HTTP Context

I'm in the process of converting user profile data that was serialized in the classic ASP.Net Membership Provider for use in SimpleMembership. I cannot figure out how to get the ProfileBase object for every user in the system.
If a specific user is logged in, I can do something like:
MyModel myModel =
(MyModel)HttpContext.Current.Profile.GetPropertyValue("MyKey");
where MyKey refers to a profile key established in web.config like this:
<add name="MyModel" type="MyNS.MyModel" serializeAs="Binary" />
However, without the benefit of an HTTP context (I'm trying to do this for all users in the system, not a logged-in user) I can't figure out how to load the profile and ultimately an instance of MyModel for each user in the system.
I have tried:
ProfileInfoCollection profiles =
ProfileManager.GetAllProfiles(ProfileAuthenticationOption.All);
foreach (var profile in profiles)
{
var pi = (ProfileBase)profile;
// OOPS! Unfortunately GetAllProfiles returns
// ProfileInfo and not ProfileCommon or ProfileBase
}
and
MembershipUserCollection existingUsers = Membership.GetAllUsers();
foreach (MembershipUser mu in existingUsers)
{
mu. // OOPS! No link to the profile from the user...
}
How can I retrieve the ProfileCommon or ProfileBase instance for each profile in the system, and thus ultimately the MyModel associated with each user?
Since I could not find an answer to this question, I opted to just read the profile data directly from SQL.
It turns out that the format is straightforward. In aspnet_Profile:
PropertyNames uses a format NameOfProperty:TypeFlag:Offset:Length (repeat for all properties).
FlagType is "S" for string or "B" for binary
Offset is the offset in the appropriate data field
Length is the length of data in the appropriate data field
PropertyValuesString holds all string properties concatenated without a delimiter.
PropertyValuesBinary holds all binary properties concatenated without a delimiter.
BinaryFormatter is used to serialize binary (non-string) properties
Here's a little code I wrote to parse the data:
private class Migrate_PropNames
{
public string Name { get; set; }
public bool IsString { get; set; }
public int Offset { get; set; }
public int Length { get; set; }
}
....
Dictionary<string, Migrate_PropNames> propInfo = ParsePropInfo(propertyNames);
// Example string property
string firstName = Migrate_GetString(propInfo["FirstName"], propertyValuesString);
// Example binary property
MyType myType =
Migrate_GetBinary<MyType>(propInfo["MyTypeKey"], propertyValuesBinary));
private T Migrate_GetBinary<T>(Migrate_PropNames propNames, byte[] propertyValuesBinary)
{
byte[] data = new byte[propNames.Length];
Array.Copy(propertyValuesBinary, propNames.Offset, data, 0, propNames.Length);
var fmt = new BinaryFormatter();
using (var ms = new MemoryStream(data))
{
T original = (T)fmt.Deserialize(ms);
return original;
}
}
private string Migrate_GetString(Migrate_PropNames propNames, string propertyNames)
{
return propertyNames.Substring(propNames.Offset, propNames.Length);
}
private Dictionary<string, Migrate_PropNames> ParsePropInfo(string propertyNames)
{
Dictionary<string, Migrate_PropNames> result = new Dictionary<string,Migrate_PropNames>();
string[] parts = propertyNames.Split(new string[] { ":"}, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < parts.Length; i += 4)
{
Migrate_PropNames pn = new Migrate_PropNames();
pn.Name = parts[i];
pn.IsString = (parts[i + 1] == "S");
pn.Offset = int.Parse(parts[i + 2]);
pn.Length = int.Parse(parts[i + 3]);
result.Add(pn.Name, pn);
}
return result;
}
I hope this helps someone. I'll gladly accept a different answer that correctly shows how to use the API.
From the ProfileInfo or MemberShipUser object, you should can get a ProfileBase one using ProfileBase.Create(string username).

name-value-pair string to Json

Trying to get an object out of str1=X&str2=Y using Newtonsoft.Json
Getting: "Unexpected character encountered while parsing value: s. Line 1, position 1."
Am i way off expecting this to work?
public class MyTest
{
public string str1 { get; set; }
public string str2 { get; set; }
}
public MyTest GetJson()
{
data = "str1=X&str2=Y";
JsonSerializerSettings jss = new JsonSerializerSettings();
jss.MissingMemberHandling = MissingMemberHandling.Error;
jss.ObjectCreationHandling = ObjectCreationHandling.Reuse;
MyTest myTest = JsonConvert.DeserializeObject<MyTest>(data, jss);
}
Yes, you're way off. json looks more like this:
{"str1":"x","str2":"y"}
See www.json.org for more information.
Edit
To convert a query string to json:
var queryString = "str1=X&str2=Y";
var queryParams = HttpUtility.ParseQueryString(queryString);
var jsonObject = new JObject(from k in queryParams.AllKeys
select new JProperty(k, queryParams[k]));
To convert a json string to an object:
MyTest test = JsonConvert.DeserializeObject<MyTest>(jsonObject.ToString());
To convert an object to json:
var test = JsonConvert.SerializeObject( new MyTest{str1 = "X", str2 = "Y"});
That's a query string, not a JSON string.
You can parse it using HttpUtility.ParseQueryString, which returns a NameValueCollection.

ASP.NET: URI handling

I'm writing a method which, let's say, given 1 and hello should return http://something.com/?something=1&hello=en.
I could hack this together pretty easily, but what abstraction functionality does ASP.NET 3.5 provide for building URIs? I'd like something like:
URI uri = new URI("~/Hello.aspx"); // E.g. ResolveUrl is used here
uri.QueryString.Set("something", "1");
uri.QueryString.Set("hello", "en");
return uri.ToString(); // /Hello.aspx?something=1&hello=en
I found the Uri class which sounds highly relevant, but I can't find anything which does the above really. Any ideas?
(For what it's worth, the order of the parameters doesn't matter to me.)
Edited to correct massively incorrect code
Based on this answer to a similar question you could easily do something like:
UriBuilder ub = new UriBuilder();
// You might want to take more care here, and set the host, scheme and port too
ub.Path = ResolveUrl("~/hello.aspx"); // Assumes we're on a page or control.
// Using var gets around internal nature of HttpValueCollection
var coll = HttpUtility.ParseQueryString(string.Empty);
coll["something"] = "1";
coll["hello"] = "en";
ub.Query = coll.ToString();
return ub.ToString();
// This returned the following on the VS development server:
// http://localhost/Hello.aspx?something=1&hello=en
This will also urlencode the collection, so:
coll["Something"] = "1";
coll["hello"] = "en&that";
Will output:
Something=1&hello=en%26that
As far I know nothing here. So everybody has its own implementation.
Example from LinqToTwitter.
internal static string BuildQueryString(IEnumerable<KeyValuePair<string, string>> parameters)
{
if (parameters == null)
{
throw new ArgumentNullException("parameters");
}
StringBuilder builder = new StringBuilder();
foreach (var pair in parameters.Where(p => !string.IsNullOrEmpty(p.Value)))
{
if (builder.Length > 0)
{
builder.Append("&");
}
builder.Append(Uri.EscapeDataString(pair.Key));
builder.Append("=");
builder.Append(Uri.EscapeDataString(pair.Value));
}
return builder.ToString();
}
UPDATE:
You can also create extension method:
public static UriBuilder AddArgument(this UriBuilder builder, string key, string value)
{
#region Contract
Contract.Requires(builder != null);
Contract.Requires(key != null);
Contract.Requires(value != null);
#endregion
var query = builder.Query;
if (query.Length > 0)
{
query = query.Substring(1) + "&";
}
query += Uri.EscapeDataString(key) + "="
+ Uri.EscapeDataString(value);
builder.Query = query;
return builder;
}
And usage:
var b = new UriBuilder();
b.AddArgument("test", "test");
Please note that everything here is untested.
Just combined answers=>
public static class UriBuilderExtensions
{
public static void AddQueryArgument(this UriBuilder b, string key, string value)
{
key = Uri.EscapeDataString(key);
value = Uri.EscapeDataString(value);
var x = HttpUtility.ParseQueryString(b.Query);
if (x.AllKeys.Contains(key)) throw new ArgumentNullException
("Key '{0}' already exists!".FormatWith(key));
x.Add(key, value);
b.Query = x.ToString();
}
public static void EditQueryArgument(this UriBuilder b, string key, string value)
{
key = Uri.EscapeDataString(key);
value = Uri.EscapeDataString(value);
var x = HttpUtility.ParseQueryString(b.Query);
if (x.AllKeys.Contains(key))
x[key] = value;
else throw new ArgumentNullException
("Key '{0}' does not exists!".FormatWith(key));
b.Query = x.ToString();
}
public static void AddOrEditQueryArgument(this UriBuilder b, string key, string value)
{
key = Uri.EscapeDataString(key);
value = Uri.EscapeDataString(value);
var x = HttpUtility.ParseQueryString(b.Query);
if (x.AllKeys.Contains(key))
x[key] = value;
else
x.Add(key, value);
b.Query = x.ToString();
}
public static void DeleteQueryArgument(this UriBuilder b, string key)
{
key = Uri.EscapeDataString(key);
var x = HttpUtility.ParseQueryString(b.Query);
if (x.AllKeys.Contains(key))
x.Remove(key);
b.Query = x.ToString();
}
}
Half baked code. But should work well enough.
There's also the UriBuilder class
This is something that might appeal to you- recently at work I was looking at a way to "type" commonly used URL query string variables and so developed this interface:
'Represent a named parameter that is passed from page-to-page via a range of methods- query strings, HTTP contexts, cookies, session, etc.
Public Interface INamedParam
'A key that uniquely identfies this parameter in any HTTP value collection (query string, context, session, etc.)
ReadOnly Property Key() As String
'The default value of the paramter.
ReadOnly Property DefaultValue() As Object
End Interface
You can then implement this interface to describe a query string parameter, such an implementation for your "Hello" param might look like this:
Public Class HelloParam
Implements INamedParam
Public ReadOnly Property DefaultValue() As Object Implements INamedParam.DefaultValue
Get
Return "0"
End Get
End Property
Public ReadOnly Property Key() As String Implements INamedParam.Key
Get
Return "hello"
End Get
End Property
End Class
I developed a small (and very, very basic) class to help build URLs using these strongly typed parameters:
Public Class ParametrizedHttpUrlBuilder
Private _RelativePath As String
Private _QueryString As String
Sub New(ByVal relativePath As String)
_RelativePath = relativePath
_QueryString = ""
End Sub
Public Sub AddQueryParameterValue(ByVal param As INamedParam, ByVal value As Object)
Dim sb As New Text.StringBuilder(30)
If _QueryString.Length > 0 Then
sb.Append("&")
End If
sb.AppendFormat("{0}={1}", param.Key, value.ToString())
_QueryString &= sb.ToString()
End Sub
Public Property RelativePath() As String
Get
Return _RelativePath
End Get
Set(ByVal value As String)
If value Is Nothing Then
_RelativePath = ""
End If
_RelativePath = value
End Set
End Property
Public ReadOnly Property Query() As String
Get
Return _QueryString
End Get
End Property
Public ReadOnly Property PathAndQuery() As String
Get
Return _RelativePath & "?" & _QueryString
End Get
End Property
End Class
Here's my version (needs .NET4 or a ToArray() call on the Select)
var items = new Dictionary<string,string> { { "Name", "Will" }, { "Age", "99" }};
String query = String.Join("&", items.Select(i => String.Concat(i.Key, "=", i.Value)));
I thought the use of Dictionary might mean the items can get reordered, but that doesn't actually seem to be happening in experiments here - not sure what that's about.

Resources