How can you get the String values from an array of objects? - c#

I have some code that basically checks the list of queues a current business object has been through. These queues are kept in an array aptly named _queueNames of type IKeyMap, a custom object my company uses.
I would like to get the textual names of the queues, as I need to check for the presence of a particular keyword and handle it separately if it's hit that particular queue.
I was hoping I could just do something like this;
var queues = _queueNames.ToArray().ToString();
if (queues.Contains("Condition"))
DoSomethingElse();
but that just gives me the object type, rather than a collection of the values. Looking at the KeyMap object, looks like just a simple key/value pair, might there be another way to do this?
Edit: KeyMap class & interface:
public interface IKeyMap : IDisposable
{
string Ley {get;}
string Field {get;}
}
public class KeyMap : IKeyMap
{
string _key, field;
public KeyMap(string key, string field)
{
_key = key;
_field = field;
}
public override string ToString()
{
return string.Format("{0}_{1}", Key, Field);
}
public string Key { get {return _key; } }
public string Field { get {return _field; } }
}
I left out some overrides, such as hashing & the Dispose method since I've got to manually type this out, can't copy-paste from my remote session :(

Without knowing what the objects inside of _queueNames look like, there is no exact answer. One mistake being made here is that you are checking a single string representing an entire array. What you want to do is check every object in the array for some value, or convert it to a string and check that value.
Here is an example:
foreach (var item in array)
{
if (item.ToString().Contains("Condition"))
{
DoSomethingElse();
break;
}
}
Or the LINQ way:
if (array.Any(item => item.ToString().Contains("Condition")))
DoSomethingElse();
This specific example only works if the object can be converted into a string that is useful to parse. You could also be accessing a member or invoking a function on said object to get your string. We can't know without more information, but hopefully this points you in the right direction.

In your IKeyMap interface, let's add a Boolean.
public string IsSpecial { get; set; }
When you create the object, set the IsSpecial flag. Then read it later..
var queues = _queueNames.ToArray().ToString();
if (queues.IsSpecial)
DoSomethingElse();
This avoids searching for strings, which is something you want to avoid. What if one of the other queues accidently end up with that string? Or what if you change the special string in one place but forget to change it in another? Or what if the capitalization is different? Or what if the string ends up with a special character that you can't see in it?
And even better way would be with an enum instead of Boolean.
public HandleType QueueHandleType {get;set;}
public enum HandleType {Normal, Special, SuperSpecial}

I might be misreading this, but is there any reason you can't just store the queues by name in array of Key/Value pairs, or even a Dictionary? For example:
var queues = new Dictionary<string, object>();
// add your queues to the dictionary, with the key name being your queue name
queues.Add("Queue1", myQueue);
// etc.
At that point you have a couple of options. First, you don't need to loop through the total set of queues you have -- you can simply do this:
var specialQueue = queues[mySpecialQueueString];
// do something with it
Or you can use LINQ to get any queues whose name contains your special string:
var results = queues.Where(keyValuePair => keyValuePair.Key.Contains(mySpecialString)).ToArray();
That said, Mason has a point in that you might need to worry about string matching and the like. There are, of course, several ways to go about this. If all queues have a fixed name then I like to make a NameConstants class with a bunch of static strings and refer to members of that class. Or you can do things like making them all upper and comparing to that.

Related

Jagged dictionary of dynamic depth?

I am trying to extract from a series of strings which represents depth like:
'foo/bar/x'
'foo/bar/baz/x'
'foo/bar/baz/x'
'foo/bar/lol/x'
Where x is a number I don't care about. I've got as far as splitting on the / and looping through, at which point in PHP I'd do something like check where in the loop I am (using for (i=0; etc)) and then use that to determine my depth to build an output array like:
output['foo']['bar'] = 1
output['foo']['bar']['baz'] = 2
output['foo']['bar']['lol'] = 1
The trouble is the 'depth' is dynamic and might be either just 3/4 deep (which I could just account for with lots of checks on the value of i and handling them separately) or say 10 or more deep in which case some kind of recursive function is probably best.
I've come across the issue that to have a string as an array index I need to use a dictionary, but you have to specify the types in the dictionary, meaning you need to know the depth in advanced (correct me if I'm wrong) when instantiating a dictionary object.
I guess an attack might be something like calling a recursive function such that each time it's called you pass i to indicate the depth, then the function calls itself decrementing i each time until it has built the portion of the tree from that input string but it's what storage structures I use for that in C# that I am not sure about.
The final output will be a CSV that I can open as a spreadsheet to look like:
Foo 0
|__Bar 1
|__Baz 2
|__Lol 1
Perhaps one direction for a solution is to use a pure C# Array and simply store the title (e.g. foo) in there, keeping information out of array indicies, which is probably best practice anyway. Thanks.
You can create your own class with following members:
class Directory
{
public int Value { get; set; }
public Dictionary<string, Directory> SubDirectories { get; set; }
}
Store your data using it and then recursively export it to CSV.
To get output["foo"]["bar"] syntax possible implement indexer within your class:
public Directory this[string name]
{
get { return SubDirectories.ContainsKey("name") ? SubDirectories[key] : null; }
set { SubDirectories.Add(name, value); }
}
While Marcin Juraszek solution is great, I just want to expand his answer just a little bit with dynamic sugar. It's not the fact, that this solution will fit your need, but just consider it as an example. I will make Directory<T> generic, so you can use whatever type for value (note that due to dynamic nature I have one cast in implementation (T)value)
class Directory<T> : DynamicObject
{
private T Value;
private Dictionary<string, Directory<T>> SubDirectories;
public Directory()
{
SubDirectories = new Dictionary<string, Directory<T>>();
}
public override bool TryGetMember(GetMemberBinder binder, out Object result)
{
if (!SubDirectories.ContainsKey(binder.Name))
SubDirectories[binder.Name] = new Directory<T>();
result = SubDirectories[binder.Name];
return true;
}
public override bool TrySetMember(SetMemberBinder binder, Object value)
{
if (!SubDirectories.ContainsKey(binder.Name))
SubDirectories[binder.Name] = new Directory<T>();
SubDirectories[binder.Name].Value = (T)value;
return true;
}
public override string ToString()
{
return Value.ToString();
}
}
And now you can use dynamic feature, available from C# 4.0
dynamic dir = new Directory<string>();
dir.foo = "Foo Value";
dir.foo.bar = "Bar Value";
dir.foo.bar.baz = "baz value";
dir.foo.bar.Lol = "Lol value";
Console.WriteLine(dir.foo.bar.Lol); //will print Lol value
Console.WriteLine(dir.foo.bar.baz); //will print baz value
which is:
Foo Foo Value
|__Bar Bar Value
|__Baz baz value
|__Lol Lol value
you can also override TryGetIndex and TrySetIndex so that you can pass complex strings, which can't be used as properties in C#

How can I avoid ref parameters?

I have a method that has 2 ref parameters:
public void ReplaceSomething(ref int code, ref string name)
{
...
}
I want to avoid this, as it is not a good design (and scales poorly). What are my options?
I've though about using an anonymous object, but that doesn't seem like a good idea, either.
Object something = new { code = 1, name = "test" };
ReplaceSomething(something);
Are the code and the name closely linked together? If so, consider creating a type to put the two of them together. Then you can return a value of that type.
Alternatively, you might consider returning a Tuple<int, string>.
(In both cases you can accept an input parameter of the same type, of course. As you haven't shown any of your code, it's not really clear whether you use the existing values of the parameters, or whether they could basically be out parameters.)
Why don't you want to use ref arguments? That seems like a perfectly good way to change some caller values.
The other approach would be to implement a return value. Maybe you need to better explain what the problem is?
If these values are tightly coupled and "belong together" you could define a custom class that holds your properties and either return a new instance (assuming its immutable) of that or update its properties:
class Code
{
public int Value {get;set;}
public string Name {get;set;}
}
public Code UpdateCode(Code code)
{
...
}
If you need to return these values, you can either use a tuple
public Tuple<int, string> ReplaceSomething(int code, string name)
{
...
}
Or create your own class-wrapper that holds the values as properties
public Foo ReplaceSomething(int code, string name)
{
var foo = new Foo(){...};
return foo;
}
class Foo
{
public int IntValue{get;set;}
public string StringValue{get;set;}
}
Why would you change it? ref parameters make sense at times, and if this is one of those times - use them. You could introduce a new class that contains that pair of values, which only makes sense if those values come together often.
I say, keep it.
Based on your question, I could be way off. What do you mean by replacing ref? Are you looking to overload?
public void ReplaceSomething(int code, string name)
{
// ...
}
public void ReplaceSomething()
{
return ReplaceSomething(1, "test");
}
Edit:
ok, so you need to return the code and the name what are the calculations that need to be made? Jon Skeet's answer about a tuple could be right, or you might need a POCO that contains the code the name and the replaced
public void ReplaceSomething(int code, string name)
{
var replaced = new Replaced();
replaced.code = code;
replaced.name = name;
var r;
// do some replacement calculations
replaced.replaced = r;
return replaced;
}
public class Replaced {
public string name {get; set;}
public int code {get; set;}
public string replaced {get; set;}
}

How best to represent form fields in C#

I'm starting to learn C# for WP7, I'm making an app to scrape various sites and display a couple of items of info off the page.
I'm going to allow the user to create multiple "accounts" on the phone - each is a set of login details for a particular site. For example, if I was to use stackoverflow as an example, I'd have a class:
public abstract class MyBaseClass
{
public Dictionary<string, string> fields;
}
public class StackOverflow : MyBaseClass
{
public StackOverflow()
{
fields.Add("Username", "Default Username");
fields.Add("Password", "");
}
}
The class will do all the work, I want people to be able to submit new classes for inclusion in later releases.
The application will iterate over each of the fields, displaying the appropriate form field to the user. Once completed, the UI will update the dictionary, ready to start scraping.
Using a dictionary seemed ok to start, but I hadn't thought about how to represent the data type - I want to define whether the input should be text, number, or password.
How would I best include that data?
Given that screen-scraping is bad at best and disasterous at worst, I must recommend that you only include sites (or serviecs) that provide a public documented API and then use that reference to define the data types that you are storing.
That said, if you're on C#/.NET 4 you might want to use the Tuple data type.
One thing to keep in mind with this pattern is that pretty much everything you do with this object is based on a "magic string". String data has very little that can be checked at compile-time; a field name referenced as a string may have a spelling mistake that would be caught immediately by the compiler; similarly, setting "ABC123" as a field that was supposed to be a decimal is just fine 'til you try and parse it out.
If you're determined to go down this path, I would change the Dictionary to a List of a custom class that contained all the metadata of the field; its name, its type, current value, etc. The list should be protected, and accessed via one or more indexers on the class that derives from your MyBaseClass class, which can pull data based on an index position OR by field name, as the situation may call for.
Be aware that in changing to a List, the naive implementation would result in a linear search time for a field, while a Dictionary gives you logarithmic access time. You can mitigate this by sorting the list and implementing a BinarySearch to find field names.
You are going to have to create your own model to represent this. Just do what comes naturally and makes sense. How about this:
public enum InputType
{
Text,
Number,
Password
}
public class Value
{
public object Value { get; set;}
public InputType InputType { get; set;}
}
public abstract class MyBaseClass
{
public Dictionary<string, Value> fields;
}
public class StackOverflow : MyBaseClass
{
public StackOverflow()
{
fields.Add("Username", new Value() {
Value = "Default Username",
InputType = InputType.Text
});
fields.Add("Password", new Value() {
Value = "hw78fksm9",
InputType = InputType.Password
});
}
}
By the way, don't make the fields variable of MyBaseClass public, this is an implementation detail and should be hidden / encapsulated!

Hash a delegate function in C#

How can I get a hash of a delegate function in C#. I want to be able to tell if different delegates are being sent into my function. My code looks something like this:
public string GetContent(Func<string, bool> isValid)
{
// Do some work
SomeFunctionToHashAFunction(isValid)
}
I would use .GetHashCode() but the .NET framework doesn't guarantee that these will be unique.
EDIT
I have some cached content that I'm validating, but I only want to validate it once. However, if the validation function changes, then I'll need to re-validate the cached content. I'm not sure if the ObjectIdGenerator will work in this instance since I need to identify if two anonymous functions have the same implementation.
By definition, a hash is not guaranteed to be unique, so hashing is not what you want.
Instead, you want to determine whether the instance of the delegate has been "seen" before. To do this, you could use ObjectIdGenerator:
private static readonly ObjectIdGenerator oidg = new ObjectIdGenerator();
public string GetContent(Func<string, bool> isValid)
{
bool firstTime;
oidg.GetId(isValid, out firstTime);
if (!firstTime)
{
...
}
}
However, even with this technique there are some pitfalls to be aware of:
ObjectIdGenerator stores a reference to each object you pass to it
Delegates to the same function are distinct objects, and would therefore return different IDs
Perhaps if you explain what it is you're trying to achieve, there may be a much better way to go about it.
EDIT: Given your updated requirements, I would just define the validation delegate as a property. If the property changes, you know you need to re-validate. GetContent() would therefore not need any parameters:
public Func<string, bool> IsValidHandler
{
get { return this.isValidHandler; }
set
{
this.isValidHandler = value;
this.requiresValidation = true;
}
}
public string GetContent()
{
if (this.requiresValidation && this.isValidHandler != null)
{
// do validation
this.requiresValidation = false;
}
// return content
}
You might even simplify further and do the validation when the IsValidHandler property is set (not in the GetContent method).
There is no (at least non completely hacky) way to hash anonymous function/delegate. Even if function implementation is the same, it might be a closure - so validation outcome might be different based on the context state. Consider this example:
public class Validator
{
public string SomeState { get; set; }
public Validator(string someState)
{
SomeState = someState;
}
public bool IsValid(string input)
{
return input == SomeState;
}
}
// assume your 'input' being validated is "foo"
GetContent((new Validator("foo")).IsValid); // IsValid returns true
GetContent((new Validator("bar")).IsValid); // IsValid returns false
So the only way be sure of whether the validation function is unique would be to have caller define uniqueness of validation implementation and have the caller pass that information to you. You would have to switch to using some kind of validator interface, something along these lines:
//
// Your code
//
public string GetContent(IValidator validator,
IEqualityComparer<IValidator> comparer)
{
// for tracking used validators, use instance
// of 'new HashSet<IValidator>(comparer)'
// this will give you a hashset of unique validators
}
public interface IValidator
{
bool IsValid(string input);
}
//
// Your callers code
//
public class Validator : IValidator
{
// same as Validator class code above
}
public class ValidatorEqualityComparer : IEqualityComparer<Validator>
{
public bool Equals(Validator v1, Validator v2)
{
return GetHashCode(v1) == GetHashCode(v2);
}
public int GetHashCode(Validator v)
{
int hCode = GetMyStringHash(v.GetType().GUID.ToString() + v.SomeState);
// as for GetMyStringHash() implementation for this example,
// you can use some simple string hashing:
// http://www.techlicity.com/blog/dotnet-hash-algorithms.html
return hCode;
}
}
Then you can call your method like this:
GetContent(new Validator("foo"), new ValidatorEqualityComparer());
So the most important part to note here, is that when implementing ValidatorEqualityComparer.GetHashCode() you use validator object state (object value based) hashing. Only this will ensure true uniqueness of validation logic.
Hashes are not intended to be unique. In terms of equality, the only thing you can use them for is to determine whether two objects are not the same. As such, they can be used as a quick first test; if the hashes are different, there is no use to do any further comparisons; the two objects are not the same. If the hashes do match, the objects may be the same, but they may also not be, so you need to perform some deeper analysis in order to determine equality.
Why not just use HashSet to store delegates? Then you can just use .Contains(isValid) to check if the delegate has been given already.
In other words, someone already solved this problem. No reason for you to also solve it.
GetHashCode WILL be unique between different object to a factor of 2^122, that seems pretty safe.
Otherwise, create a class, add a func property, and a bool that is, HasBeenSeen.
Should get the job done.

Dynamic Linq Library Help

I have the following class:
public class Item
{
public Dictionary<string, string> Data
{
get;
set;
}
}
and a list of it:
List<Item> items;
I need to filter and order this list dynamically using SQL-Like strings. The catch is, that I need to order it by the Data dictionary.
For example: Order By Data["lastname"] or Where Data["Name"].StartsWith("a"). I thought to use the dynamic linq library, but is there any way that my clients can write without the Data[]? For example:
Name.StartsWith("abc")
instead of
Data["Name"].StartsWith("abc")
?
You could add a property like this:
public class Item
{
public Dictionary<string, string> Data
{ get; set; }
public string Name { get { return Data["lastname"]; } }
}
//Call by: i.Name.StartsWith("abc");
Or an extension method:
public static class ItemExtensions
{
public static string Name(this Item item)
{
return item.Data["lastname"];
}
}
//Call by: i.Name().StartsWith("abc");
Or if it's a very commonly used method, you could add something like a .NameStartsWith():
public static string NameStartsWith(this Item item, stirng start)
{
return item.Data["lastname"].StartsWith(start);
}
//Call by: i.NameStartsWith("abc");
This doesn't have anything to do with the Linq Dynamic Query unit. That unit is for when you have actual fields/properties and the names of them will be given to you at runtime. In other words, you have a class like this:
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
And you want to be able to write a query like this:
var sortedPeople = people.OrderBy("FirstName");
You are trying to do the exact opposite of this - you have a class that does not have any actual properties, just an attribute dictionary, and you want compile-time safety. You can't have it; there's no way to guarantee that an item will be in the dictionary, especially when the dictionary is public and anyone can add/remove directly from it!
If there's some reason that you must use that specific class design, then you could conceivably write some wrappers as Nick has presented, but I wouldn't even bother - they're not actually providing any encapsulation because the Data dictionary is still wide open to the whole world. Instead, I would just provide a single safe getter method or indexer property and create a few constants (or an enum) with the names of properties you expect to be in there.
public class Item
{
public Dictionary<string, string> Data { get; set; }
public string GetValue(string key)
{
if (Data == null)
return null;
string result;
Data.TryGetValue(key, out result);
return result;
}
}
public class ItemKeys
{
public const string Name = "Name";
public const string Foo = "Foo";
}
And so on. Really the ItemKeys isn't that important, the safe GetValue method is what's important, because otherwise you run the risk of a NullReferenceException if Data hasn't been assigned, or a KeyNotFoundException if even one Item instance doesn't have that property. Using the GetValue method here will succeed no matter what:
var myItems = items.OrderBy(i => i.GetValue(ItemKeys.Name));
If you find you're writing a lot of repetitive code for the same attributes, then start worrying about adding shortcut properties or extension methods to the class.
I assume that you don't know the names of the properties at compile-time (in which case, you could simply define properties and wouldn't have this problem). I have two suggestions that you could try, but I didn't implement any of them myself, so I can't guarantee that it will work.
If you can use .NET 4.0, you could inherit from DynamicObject and implement TryGetMember method (which is called when you use o.Foo on an object that is declared as dynamic). Assuming that Dynamic LINQ works with DLR, it should automatically invoke this method for objects that inherit from DynamicObject. Inside the TryGetMember method, you would get a name of the accessed property, so you could perform a dictionary lookup. (However, this solution would work only if Dynamic LINQ integrates well with DLR).
In any case, you could do some basic parsing of the string entered by the user and replace for example Name with Data["Name"]. This would definitely work, but it may be a bit difficult (because you should probably at least check that you're doing the replace in correct context - e.g. not inside a string constant).
Regarding extension methods - I'm not sure if Dynamic LINQ handles extension methods (but, I don't think so, because that would require searching all referenced assemblies)

Categories

Resources