At times when we access Session["key"].ToString() it gives exception when session is expired & in coding we try to access session variable. So I'm trying to create extension method on object class so that I could write it as Session["key"].getString() in coding so that every time I don't have to do Convert.ToString(session["key"])
Any other solutions are also appreciable.
Just use the null-coalescing operator:
string value = (session["key"] ?? String.Empty).ToString();
Update
If you must have a method to do this (extension or otherwise), I would do something like:
public static string GetValue(this HttpSessionState session, string key)
{
// TODO: Insert appropriate error checking here.
return (session[key] ?? String.Empty).ToString();
}
I might even go so far as to make it generic for other possible types with a GetValue call that takes a selector and then use lambdas:
public static T GetValue<T>(this HttpSessionState session, string key, Func<object, T> valueSelector)
{
return valueSelector(session[key]);
}
public static string GetStringValue(this HttpSessionState session, string key)
{
return session.GetValue(key, x => (x ?? String.Empty).ToString());
}
You would then use as follows:
string value = session.GetStringValue("key");
public static class ObjectExtensions
{
public static string GetString(this object o)
{
if (o == null)
{
return string.Empty;
}
return Convert.ToString(o);
}
}
and then:
string value = Session["key"].GetString();
or check this one:
public static class SessionExtensions
{
public static string GetString(this HttpSessionStateBase session, string key)
{
if (session == null)
{
return string.Empty;
}
var value = session[key];
if (value == null)
{
return string.Empty;
}
return Convert.ToString(value);
}
}
and then:
string value = Session.GetString("key");
Maybe this can ba an alternative?
object oKey = session["key"] ?? String.Empty;
string sKey = (string)oKey;
or
string sKey = session["key"] == null ? String.Empty : (string)session["key"]
public static class ObjectExtensions
{
public static string SafelyToString(this object o)
{
return o != null ? o.ToString() : string.Empty;
}
}
This will allow Session["key"].SafelyToString()
You will not however be able to discern between an empty string in the session variable and an expired session.
I would also advise using properties for that.
protected YourType PropertyName
{
get
{
if(Session["Sessionname"] != null)
{
return Session["Sessionname"] as YourType;
}
YourType newItem = new YourType();
// set vars
Session["Sessionname"] = newItem;
return newItem;
}
set
{
Session["Sessionname"] = value;
}
}
As you can see, I chose protected as access modifier. If you want you could put it in a public class and make the property static.
Or you can use class that derives from System.Web.UI.Page.
public class MyCustomBaseClass : System.Web.UI.Page
{
protected YourType PropertyName
{
// get and set like above
}
}
Now you can replace the inheritance in your content pages from System.Web.UI.Page to MyCustomBaseClass and can easily call this.PropertyName.
Here is a easy way to access Session in Extension method:
var loggedUser = (User)System.Web.HttpContext.Current.Session["User"];
Related
C# has the usefull Null Conditional Operator. Well explained in this answer too.
I was wondering if it is possible to do a similar check like this when my object is a dynamic/expando object. Let me show you some code:
Given this class hierarchy
public class ClsLevel1
{
public ClsLevel2 ClsLevel2 { get; set; }
public ClsLevel1()
{
this.ClsLevel2 = new ClsLevel2(); // You can comment this line to test
}
}
public class ClsLevel2
{
public ClsLevel3 ClsLevel3 { get; set; }
public ClsLevel2()
{
this.ClsLevel3 = new ClsLevel3();
}
}
public class ClsLevel3
{
// No child
public ClsLevel3()
{
}
}
If i perform this kind of chained null check, it works
ClsLevel1 levelRoot = new ClsLevel1();
if (levelRoot?.ClsLevel2?.ClsLevel3 != null)
{
// will enter here if you DO NOT comment the content of the ClsLevel1 constructor
}
else
{
// will enter here if you COMMENT the content of the ClsLevel1
}
Now, i will try to reproduce this behaviour with dynamics (ExpandoObjects)
dynamic dinRoot = new ExpandoObject();
dynamic DinLevel1 = new ExpandoObject();
dynamic DinLevel2 = new ExpandoObject();
dynamic DinLevel3 = new ExpandoObject();
dinRoot.DinLevel1 = DinLevel1;
dinRoot.DinLevel1.DinLevel2 = DinLevel2;
//dinRoot.DinLevel1.DinLevel2.DinLevel3 = DinLevel3; // You can comment this line to test
if (dinRoot?.DinLevel1?.DinLevel2?.DinLevel3 != null)
{
// Obviously it will raise an exception because the DinLevel3 does not exists, it is commented right now.
}
Is there a way to simulate this behaviour with dynamics? I mean, check for a null in a long chain of members?
If you want to support this in a more natural way you can inherit from DynamicObject and provide a custom implementation:
class MyExpando : DynamicObject
{
private readonly Dictionary<string, object> _dictionary = new Dictionary<string, object>();
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var name = binder.Name.ToLower();
result = _dictionary.ContainsKey(name) ? _dictionary[name] : null;
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_dictionary[binder.Name.ToLower()] = value;
return true;
}
}
Testing:
private static void Main(string[] args)
{
dynamic foo = new MyExpando();
if (foo.Boo?.Lol ?? true)
{
Console.WriteLine("It works!");
}
Console.ReadLine();
}
The output will be "It works!". Since Boo does not exist we get a null reference so that the Null Conditional Operator can work.
What we do here is to return a null reference to the output parameter of TryGetMember every time a property is not found and we always return true.
EDIT: fixed, as ExpandoObjects and extension methods do not work well together. Slightly less nice, but hopefully still usable.
Helper method(s):
public static class DynamicExtensions
{
public static Object TryGetProperty(ExpandoObject obj, String name)
{
return name.Split('.')
.Aggregate((Object)obj, (o, s) => o != null
? TryGetPropertyInternal(o, s)
: null);
}
private static Object TryGetPropertyInternal(Object obj, String name)
{
var dict = obj as IDictionary<String, Object>;
return (dict?.ContainsKey(name) ?? false) ? dict[name] : null;
}
}
Usage:
if (DynamicExtensions.TryGetProperty(dinRoot, "DinLevel1.DinLevel2.DinLevel3") != null)
I am trying to figure out why I am getting an invalid cast exception with nHibernate with the following code:
AutoMap.Source(new TypeSource(recordDescriptors))
.Conventions.Add(new EncryptedStringConvention());
.
[AttributeUsage(AttributeTargets.Property)]
public class EncryptedDbString : Attribute { }
.
public class EncryptedStringConvention : IPropertyConvention {
public void Apply(IPropertyInstance instance) {
if (!instance.Property.MemberInfo.IsDefined(typeof(EncryptedDbString), false))
return;
var propertyType = instance.Property.PropertyType;
var generic = typeof(EncryptedStringType<>);
var specific = generic.MakeGenericType(propertyType);
instance.CustomType(specific);
}
}
.
[Serializable]
public class EncryptedStringType<T> : PrimitiveType
{
const int MaxStringLen = 1000000000;
public EncryptedStringType() : this(new StringSqlType(MaxStringLen)) { }
public EncryptedStringType(SqlType sqlType) : base(sqlType) { }
public override string Name {
get { return typeof(T).Name; }
}
public override Type ReturnedClass {
get { return typeof(T); }
}
public override Type PrimitiveClass {
get { return typeof(T); }
}
public override object DefaultValue {
get { return default(T); }
}
public override object Get(IDataReader rs, string name) {
return Get(rs, rs.GetOrdinal(name));
}
public override void Set(IDbCommand cmd, object value, int index) {
if (cmd == null) throw new ArgumentNullException("cmd");
if (value == null) {
((IDataParameter)cmd.Parameters[index]).Value = null;
}
else {
((IDataParameter)cmd.Parameters[index]).Value = Encryptor.EncryptString((string)value);
}
}
public override object Get(IDataReader rs, int index) {
if (rs == null) throw new ArgumentNullException("rs");
var encrypted = rs[index] as string;
if (encrypted == null) return null;
return Encryptor.DecryptString(encrypted);
}
public override object FromStringValue(string xml) {
// i don't think this method actually gets called for string (i.e. non-binary) storage
throw new NotImplementedException();
}
public override string ObjectToSQLString(object value, Dialect dialect) {
// i don't think this method actually gets called for string (i.e. non-binary) storage
throw new NotImplementedException();
}
}
POCO that works:
public class someclass {
public virtual string id {get;set;}
[EncryptedDbString]
public virtual string abc {get;set;}
}
POCO that fails:
public class otherclass {
public virtual string id {get;set;}
[EncryptedDbString]
public virtual Guid def {get;set;}
}
This is all automapped with Fluent.
Both the Guid type and string type are nvarchar(500) in the SQL database.
As mentioned, the first POCO works fine and encrypts/decrypts as expected, but the second POCO fails, and this is what I see in my logs:
NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValuesWithOptimizer(Object entity, Object[] values)
{"Invalid Cast (check your mapping for property type mismatches); setter of otherclass"}
Note that the second POCO object works fine with nHib if I remove the EncryptedDbString attibute, i.e. it has no problems saving the Guid to a nvarchar.
Obviously the issue here is that it's a Guid as the string case works, but I do want it kept as a Guid not a string in the code, and I can't see the point of failure here.
Seems like I'm missing something small. I guess I'm missing something with the generics, but I've only found code snippets out there rather than a full example like this.
EDIT:
ok, so i figured out it i think it was because the
Get(IDataReader rs, int index)
was not returning a Guid object.
so I guess you can serialize/deserialize in the EncryptedStringType Get/Set methods, e.g. in the Get() you could change to:
if (typeof(T) == typeof(string))
return decrypted;
var obj = JsonConvert.DeserializeObject(decrypted);
return obj;
but that seems horrible, especially if you have existing data to migrate.
i don't want to store stuff as binary either, as the team want to be able to check/test/audit manually via SQL which columns are encrypted (which is obvious with text, but not binary).
a string backing field in my POCO that converts the Guid to a string and back again via simple get/set methods might be the best option, but I have no idea how to do that with automapping across the solution or how messy it is?
Having slept, I think i've been thinking about this the wrong way.
I've now realised that my reticence to store json in the database was driven by the fact that I am storing string-biased objects - i.e. things that naturally convert to text fields, as opposed to full objects. myGuid.ToString() gives you a guid string, myDateTime.ToString() gives you a datetime string etc.
So given that object serialisation per se isn't needed in my case, but rather just conversion to a string, Andrew's suggestion seems like a good solution.
Updated code:
public override void Set(IDbCommand cmd, object value, int index) {
var prm = ((IDataParameter) cmd.Parameters[index]);
if (cmd == null) throw new ArgumentNullException("cmd");
if (value == null) {
prm.Value = null;
return;
}
string str;
try {
// guid becomes a simple guid string, datetime becomes a simple
// datetime string etc. (ymmv per type)
// note that it will use the currentculture by
// default - which is what we want for a datetime anyway
str = TypeDescriptor.GetConverter(typeof(T)).ConvertToString(value);
}
catch (NotSupportedException) {
throw new NotSupportedException("Unconvertible type " + typeof(T) + " with EncryptedDbString attribute");
}
prm.Value = Encryptor.EncryptString(str);
}
public override object Get(IDataReader rs, int index) {
if (rs == null) throw new ArgumentNullException("rs");
var encrypted = rs[index] as string;
if (encrypted == null) return null;
var decrypted = Encryptor.DecryptString(encrypted);
object obj;
try {
obj = (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(decrypted);
}
catch (NotSupportedException) {
throw new NotSupportedException("Unconvertible type " + typeof(T) + " with EncryptedDbString attribute");
}
catch (FormatException) {
// consideration - this will log the unencrypted text
throw new FormatException(string.Format("Cannot convert string {0} to type {1}", decrypted, typeof(T)));
}
return obj;
}
An improvement would be for the EncryptedStringConvention to have the Accept() method added to pre-check that all the types marked with the EncryptedDbString attribute were convertible. Possibly we could use Convert() and type is IConvertible instead, but I'll leave it as, enough time spent!
I have a scenario where I need the properties in my class to map to a dictionary. Here is a code sample:
public string Foo
{
get
{
if (!PropertyBag.ContainsKey("Foo"))
{
return null;
}
return PropertyBag["Foo"];
}
set
{
PropertyBag["Foo"] = value;
}
}
I have to apply this pattern to multiple properties. Is there a way to use attributes to do that?
I know that PostSharp would work for this purpose, but I was hoping there is a way to do it without using it.
This feels like a code smell to me. It would be better to use regular POCOs and convert them to a Dictionary only when needed.
public class BlogPost
{
public string Title { get; set; }
public string Body { get; set; }
public int AuthorId { get; set; }
public Dictionary<string, object> ToDictionary()
{
return this.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.ToDictionary(prop => prop.Name, prop => prop.GetValue(this, null));
}
}
Inspiration: How to convert class into Dictionary?
And to be honest, a ToDictionary method on your POCO's seems like a code smell. It would be better to refactor your code so the conversion of POCOs to Dictionaries happens in its own layer, as a service maybe.
Edit: This Gist I found while searching google for "c# convert object to dictionary" could provide a more generalized solution, and probably more bullet proof than my cobbled together example:
Gist: https://gist.github.com/jarrettmeyer/798667
From the Gist:
public static class ObjectToDictionaryHelper
{
public static IDictionary<string, object> ToDictionary(this object source)
{
return source.ToDictionary<object>();
}
public static IDictionary<string, T> ToDictionary<T>(this object source)
{
if (source == null)
ThrowExceptionWhenSourceArgumentIsNull();
var dictionary = new Dictionary<string, T>();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
AddPropertyToDictionary<T>(property, source, dictionary);
return dictionary;
}
private static void AddPropertyToDictionary<T>(PropertyDescriptor property, object source, Dictionary<string, T> dictionary)
{
object value = property.GetValue(source);
if (IsOfType<T>(value))
dictionary.add(property.Name, (T)value);
}
private static bool IsOfType<T>(object value)
{
return value is T;
}
private static void ThrowExceptionWhenSourceArgumentIsNull()
{
throw new ArgumentNullException("source", "Unable to convert object to a dictionary. The source object is null.");
}
}
Credit: jerrettmeyer at GitHub
This should add a ToDictionary method to every object.
Edit: From the following comment
To give a bit of context, I am using Entity Framework and I have a class hierarchy that I would like to keep in one table while avoiding null columns everywhere.
Entity framework supports multiple table inheritance. That might be a better solution in your case.
You can write a GetValueOrDefault extension method and reduce the code a little.
public static class DictionaryExtensions
{
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey,TValue> self, TKey key)
{
TValue value;
self.TryGetValue(key,out value);
return value;
}
}
public string Foo
{
get
{
return PropertyBag.GetValueOrDefault("Foo");
}
set
{
PropertyBag["Foo"] = value;
}
}
You can eliminate the magic strings using expressions.
If you're using at least .NET 4.5 then you have the CallerMemberNameAttribute which you could use like this:
class SomeClass
{
public string Foo
{
get
{
return GetPropertyValue();
}
set
{
SetPropertyValue( value );
}
}
private string GetPropertyValue( [CallerMemberName] string name = null )
{
string value;
PropertyBag.TryGetValue( name, out value );
return value;
}
private void SetPropertyValue( string value, [CallerMemberName] string name = null )
{
PropertyBag[name] = value;
}
}
This will result in the compiler filling out the name of the member for you. If you're not (or otherwise can't) use .NET 4.5, another alternative would be to take advantage of expression trees as suggested in another answer.
class Test
{
Dictionary<string,object> _values = new Dictionary<string, object>();
public string Foo
{
get
{
var value = GetValue();
return value == null ? string.Empty : (string)value;
}
set
{
SetValue(value);
}
}
private object GetValue()
{
var stack = new StackTrace();
var key = GetGenericName(stack.GetFrame(1).GetMethod().Name);
if (_values.ContainsKey(key)) return _values[key];
return null;
}
private void SetValue(object value)
{
var stack = new StackTrace();
var key = GetGenericName(stack.GetFrame(1).GetMethod().Name);
_values[key] = value;
}
private string GetGenericName(string key)
{
return key.Split('_')[1];
}
}
I have the following:
var result2 = result1
.Select((t, index) => new {
Answer = t.Answer,
Answers = JSON.FromJSONString<Answer2>(t.AnswerJSON)
});
return Ok(result2);
public class Answer2 {
public bool? Correct; // Maybe this should be a property
public bool Response; // Maybe this should be a property
}
And my String > object function:
public static T FromJSONString<T>(this string obj) where T : class
{
if (obj == null)
{
return null;
}
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(obj)))
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
T ret = (T)ser.ReadObject(stream);
return ret;
}
}
Is there a way with this that I could make the Response field be false if a null is present for Response in the JSON string or if there is no value for Response in the JSON string?
Note: I had a suggestion about using a property and I think that would work but I am not sure how to do it in practice.
You should use a property for this matter:
public class Answer2 {
private bool correct; // This field has no need to be nullable
public bool? Correct
{
get { return correct; }
set { correct = value.GetValueOrDefault(); }
}
}
Following the Q and A section, you should be able to do it on a property like this:
private bool? whatever;
public bool? Whatever
{
get { return whatever; }
set
{
if (value == null)
whatever = false;
else
whatever = value;
}
}
This way you can pass a null value to the property, but it can only have a bool (true/false) value in it.
is there a way to get the value of a property of a object based on its name?
For example if I have:
public class Car : Vehicle
{
public string Make { get; set; }
}
and
var car = new Car { Make="Ford" };
I want to write a method where I can pass in the property name and it would return the property value. ie:
public string GetPropertyValue(string propertyName)
{
return the value of the property;
}
return car.GetType().GetProperty(propertyName).GetValue(car, null);
You'd have to use reflection
public object GetPropertyValue(object car, string propertyName)
{
return car.GetType().GetProperties()
.Single(pi => pi.Name == propertyName)
.GetValue(car, null);
}
If you want to be really fancy, you could make it an extension method:
public static object GetPropertyValue(this object car, string propertyName)
{
return car.GetType().GetProperties()
.Single(pi => pi.Name == propertyName)
.GetValue(car, null);
}
And then:
string makeValue = (string)car.GetPropertyValue("Make");
You want Reflection
Type t = typeof(Car);
PropertyInfo prop = t.GetProperty("Make");
if(null != prop)
return prop.GetValue(this, null);
Expanding on Adam Rackis's answer - we can make the extension method generic simply like this:
public static TResult GetPropertyValue<TResult>(this object t, string propertyName)
{
object val = t.GetType().GetProperties().Single(pi => pi.Name == propertyName).GetValue(t, null);
return (TResult)val;
}
You can throw some error handling around that too if you like.
In addition other guys answer, its Easy to get property value of any object by use Extension method like:
public static class Helper
{
public static object GetPropertyValue(this object T, string PropName)
{
return T.GetType().GetProperty(PropName) == null ? null : T.GetType().GetProperty(PropName).GetValue(T, null);
}
}
Usage is:
Car foo = new Car();
var balbal = foo.GetPropertyValue("Make");
Simple sample (without write reflection hard code in the client)
class Customer
{
public string CustomerName { get; set; }
public string Address { get; set; }
// approach here
public string GetPropertyValue(string propertyName)
{
try
{
return this.GetType().GetProperty(propertyName).GetValue(this, null) as string;
}
catch { return null; }
}
}
//use sample
static void Main(string[] args)
{
var customer = new Customer { CustomerName = "Harvey Triana", Address = "Something..." };
Console.WriteLine(customer.GetPropertyValue("CustomerName"));
}
To avoid reflection you could set up a Dictionary with your propery names as keys and functions in the dictionary value part that return the corresponding values from the properties that you request.
2 Very short options, 1 with a default value if it fails:
public object GetPropertyValue_WithDefault(
object _t,
string _prop,
object _default = null
)
{
PropertyInfo pi = _t.GetType().GetProperty(_prop);
return (pi == null
? _default
: pi.GetValue(_t, null)
);
}
public object GetPropertyValue(object _t, string _prop)
{
//because of "?." will return null if property not found
return _t.GetType().GetProperty(_prop)?.GetValue(_t, null);
}