Rename interface using Roslyn not working - c#

I want to rename a class, its base class and the interface that it supports. For example I want to rewrite this:-
public class CustomerDAL : DALBase, ICustomerDAL
to this:-
public class CustomerRepository : RepositoryBase, ICustomerRepository
So I wrote this CSharpSyntaxRewriter:-
public class RenameBaseClassAndInterface : CSharpSyntaxRewriter
{
public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
{
if (node.Identifier.Text.Contains("DAL"))
{
string className = node.Identifier.Text.Replace("DAL", "Repository");
node = node.ReplaceToken(node.Identifier, SyntaxFactory.Identifier(className));
if (node.BaseList != null && node.BaseList.Types != null)
{
foreach (BaseTypeSyntax baseTypeSyntax in node.BaseList.Types)
{
TypeSyntax typeSyntax = baseTypeSyntax.Type;
IdentifierNameSyntax identifierNameSyntax = (IdentifierNameSyntax)typeSyntax;
if (identifierNameSyntax.Identifier.ToString() == "DALBase")
{
node = node.ReplaceToken(identifierNameSyntax.Identifier, SyntaxFactory.Identifier("RepositoryBase"));
}
else if (identifierNameSyntax.Identifier.ToString().Contains("DAL"))
{
string repositoryInterfaceName = identifierNameSyntax.Identifier.ToString().Replace("DAL", "Repository");
node = node.ReplaceToken(identifierNameSyntax.Identifier, SyntaxFactory.Identifier(repositoryInterfaceName));
}
}
}
}
return base.VisitClassDeclaration(node);
}
}
What I actually get is this:-
public class CustomerRepository : RepositoryBase, ICustomerDAL
(i.e. ICustomerDAL does not get renamed to ICustomerRepository).
I can step through my code and I see that it reaches and executes the code to rename the interface and no error occurs, it just doesn't work. I suspect that this is because it is doing the rename on an old node and not the new node but I can't see what I have done wrong.
Any ideas?

You have your foreach loop that is trying to update all of the tokens in the base list. Once you do the first call to ReplaceToken, you've created a new node that has new identity of tokens, so the second time you call you're ReplaceToken, you're passing in a token from the original node to the call that's happening on the new node. So the second call is probably returning the existing node rather than doing a replacement. (Unfortunately ReplaceToken is a no-op if it can't find the token, which is often confusing.)
Instead of your foreach loop as written, add the tokens that need replacing (or at least analysis) into a list, and then call ReplaceTokens. This takes a list of tokens to (potentially) replace, and a lambda that we'll call for each token to rewrite it.

public override SyntaxNode VisitBaseList(BaseListSyntax node)
{
if (node.Parent is ClassDeclarationSyntax cds && cds.Identifier.Text.Contains("DAL"))
{
BaseTypeSyntax baseType = SyntaxFactory.SimpleBaseType(SyntaxFactory.ParseTypeName("RepositoryBase"));
//...
var repositoryTypeName = SyntaxFactory.ParseTypeName(repositoryInterfaceName);
BaseTypeSyntax repositoryInterface = SyntaxFactory.SimpleBaseType(repositoryTypeName);
return SyntaxFactory.BaseList().AddTypes(baseType, repositoryInterface).NormalizeWhitespace();
}
return base.VisitBaseList(node);
}

Related

How do I get autoproperties on one line when generating code with Roslyn?

I have the following partial code which I use to generate datacontracts based on an excel-file we use for customer facing workshops and such.
private PropertyDeclarationSyntax[] GenerateProperties()
{
var props = new List<PropertyDeclarationSyntax>();
props.Add(SF.PropertyDeclaration(SF.ParseTypeName("IMigrationInformation"), "MigrationInformation")
.AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.OverrideKeyword))
.AddAccessorListAccessors(
SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithBody(SF.Block(SF.ReturnStatement(SF.ObjectCreationExpression(SF.ParseTypeName($"{Form.RegistryName}MigrationInformation")))))
));
foreach (var field in Form.AllDataFields().Where(f => f.FieldTypeInfo != null))
{
props.Add(SF.PropertyDeclaration(SF.ParseTypeName(field.FieldTypeInfo.BackingType.Name), field.SafeName)
.AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken)),
SF.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken))
));
}
return props.ToArray();
}
The code works surprisingly well with one small snag. The code generated looks like this:
public string VariableName
{
get;
set;
}
And I really want it to look like this:
public string VariableName { get; set; }
Does anyone know how to do this, if possible?
I got the exact same problem. In my case, I was saving the code to file after converting it to a string something like this:
private void WriteCodeToFile(NamespaceDeclarationSyntax ns)
{
var codeAsString = ns.NormalizeWhitespace()
.ToFullString();
File.WriteAllText(destFileName, codeAsString);
}
So, in that case, I just solved it byrunning a regex replace on the string, in an extension method:
private static readonly Regex AutoPropRegex = new Regex(#"\s*\{\s*get;\s*set;\s*}\s");
public static string FormatAutoPropertiesOnOneLine(this string str)
{
return AutoPropRegex.Replace(str, " { get; set; }");
}
And then call it after converting it to string:
var codeAsString = ns.NormalizeWhitespace()
.ToFullString()
.FormatAutoPropertiesOnOneLine();
You are not speficying how you do your file-writing step (if any), so if this is not relevant at all in your case, I apologize for not targeting your question 100%. In any case, someone else might benefit from it.
You could implement a CSharpSyntaxRewriter and than apply it to a parent SyntaxNode:
public static class WhitespaceFormatter
{
public static SyntaxNode NormalizeWhitespacesSingleLineProperties(this SyntaxNode node) =>
node.NormalizeWhitespace().SingleLineProperties();
public static SyntaxNode SingleLineProperties(this SyntaxNode node) => new SingleLinePropertyRewriter().Visit(node);
class SingleLinePropertyRewriter : CSharpSyntaxRewriter
{
public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node) =>
node.NormalizeWhitespace(indentation: "", eol: " ")
.WithLeadingTrivia(node.GetLeadingTrivia())
.WithTrailingTrivia(node.GetTrailingTrivia());
}
}
Use NormalizeWhitespacesSingleLineProperties to apply default whitespaces to everything but property declarations which will be written to a single line. Make sure not to call Format or NormalizeWhitespace() on your node afterwards, because it will again clutter your property declarations.
As one of simple solution (another way create a nodes and tokens with correct trivias) just use SyntaxNodeExtensions.NormalizeWhitespace(...) for nodes that you want to represent at the one line:
...
foreach (var field in Form.AllDataFields().Where(f => f.FieldTypeInfo != null))
{
props.Add(SF.PropertyDeclaration(SF.ParseTypeName(field.FieldTypeInfo.BackingType.Name), field.SafeName)
.AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken)),
SF.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken))
).NormalizeWhitespace(indentation: "", eol: " "));
}

Function which will return particular node from tree structure

I am writing the function which will return particular node from tree structure. But when I search in a tree using LINQ it is searching in the first branch and finally when it reaches to leaf it is throwing null reference exception as leaf don't have any child.
Here is my class,
public class Node
{
public int Id { get; set; }
public string Name { get; set; }
public string Content { get; set; }
public IEnumerable<Node> Children { get; set; }
public IEnumerable<Node> GetNodeAndDescendants() // Note that this method is lazy
{
return new[] { this }
.Concat(Children.SelectMany(child => child.GetNodeAndDescendants()));
}
}
This is how I am calling this function,
var foundNode = Location.GetNodeAndDescendants().FirstOrDefault(node => node.Name.Contains("string to search"));
OR
var foundNode = Location.GetNodeAndDescendants().FirstOrDefault(node => node.Id==123)
What would be the correct way to do this? and any sample code would be grateful
Nothing wrong to write your own function, but implementation based on LINQ or recursive iterator is not a good idea (performance!). But why depending on external libraries? A lot of code that you don't need, implementing interfaces, modifying your classes etc. It's not hard to write a generic function for pre-order tree traversal and use it for any tree structure. Here is a modified version of my participation in How to flatten tree via LINQ? (nothing special, ordinary iterative implementation):
public static class TreeHelper
{
public static IEnumerable<T> PreOrderTraversal<T>(T node, Func<T, IEnumerable<T>> childrenSelector)
{
var stack = new Stack<IEnumerator<T>>();
var e = Enumerable.Repeat(node, 1).GetEnumerator();
try
{
while (true)
{
while (e.MoveNext())
{
var item = e.Current;
yield return item;
var children = childrenSelector(item);
if (children == null) continue;
stack.Push(e);
e = children.GetEnumerator();
}
if (stack.Count == 0) break;
e.Dispose();
e = stack.Pop();
}
}
finally
{
e.Dispose();
while (stack.Count != 0) stack.Pop().Dispose();
}
}
}
and your function inside the class Node becomes:
public IEnumerable<Node> GetNodeAndDescendants() // Note that this method is lazy
{
return TreeHelper.PreOrderTraversal(this, node => node.Children);
}
Everything else stays the way you did it and should work w/o any problem.
EDIT: Looks like you need something like this:
public interface IContainer
{
// ...
}
public class CustomerNodeInstance : IContainer
{
// ...
}
public class ProductNodeInstance : IContainer
{
// ...
}
public class Node : IContainer
{
// ...
public IEnumerable<IContainer> Children { get; set; }
public IEnumerable<IContainer> GetNodeAndDescendants() // Note that this method is lazy
{
return TreeHelper.PreOrderTraversal<IContainer>(this, item => { var node = item as Node; return node != null ? node.Children : null; });
}
}
If you don't mind taking a dependency on a third party solution I have a lightweight library that I have been working on that can do this and many other things with just about any tree. It is called Treenumerable. You can find it on GitHub here: https://github.com/jasonmcboyd/Treenumerable; and the latest version (1.2.0 at this time) on NuGet here: http://www.nuget.org/packages/Treenumerable. It has good test coverage and seems to be stable.
It does require that you create a helper class that implements an ITreeWalker interface with two methods: TryGetParent and GetChildren. As you might guess TryGetParent gets a node's parent so your Node class would have to be modified in a way that it is aware of its parent. I guess you could just throw a NotSupported exception in TryGetParent as that method is not necessary for any of the traversal operations. Anyway, regardless of which way you go the following code would do what you want:
ITreeWaler<Node> walker;
// Don't forget to instantiate 'walker'.
var foundNode =
walker
.PreOrderTraversal(Location)
.FirstOrdefault(node => node.Name.Contains("string to search"));
One difference worth mentioning between my implementation and yours is that my implementation does not rely on recursion. This means you don't have to worry about a deep tree throwing a StackOverflowException.

Converting between polymorphic object graphs

lengthy software architecture question ahead
CLARITY EDIT: I am trying to convert an object graph that consists of types like
NodeA, NodeB, ... to an object graph that consists of types like *My*NodeA, *My*NodeB ..., and vice versa. The properties in the NodeX types correspond to similar properties in the MyNodeX types, but in many cases it is not just a trivial assignment.
If I have two similar class structures like this:
// pure model, i.e. minimal information that is convenient for storage
abstract class Node
{
public int BaseProperty { get; set; }
public NodeCollection Children { get; private set; } // : Collection<Node>
}
class NodeA /* NodeB, NodeC ... */ : Node
{
public int DerivedAProperty { get; set; }
}
and
// objects that are convenient for being used by the application
abstract class MyNode
{
public int MyBaseProperty { get; set; }
public MyNodeCollection Children { get; private set; } // : Collection<MyNode>
}
class MyNodeA /* MyNodeB, MyNodeC ... */ : MyNode
{
public int MyDerivedAProperty { get; set; }
}
, and I need to convert an object graph of the NodeX type to one of the MyNodeX type, or vice versa, without changing any of the NodeX classes at all, I've found myself using this pattern regularly:
NodeX -> MyNodeX
// USAGE / external code
Node node = ...
MyNode myNode = MyNode.Load(node, ARGS); // static factory
abstract class MyNode
{
...
// factory
public static MyNode Load(Node node, ARGS)
{
var type = node.GetType();
MyNode myNode;
// no 'is' usage because NodeB could be derived from NodeC etc.
if (type == typeof(NodeA))
myNode = new MyNodeA(ARGS); // arbitrary ctor
else if (...)
...
myNode.Load(Node);
return myNode
}
public virtual void Load(Node node)
{
this.MyBaseProperty = node.BaseProperty;
foreach (var child in node.Children)
this.Children.Add(MyNode.Load(child, this.ARGS));
}
}
class MyNodeA : MyNode
{
...
public override void Load(Node node)
{
var m = (NodeA)node; // provoke InvalidCastException if coding error
base.Load(node);
this.MyDerivedAProperty = m.DerivedAProperty;
}
}
MyNodeX -> NodeX
// USAGE / external code
MyNode myNode = ...
Node node = myNode.Commit();
abstract class MyNode
{
...
// 'kind of' factory
public abstract Node Commit();
public virtual Commit(Node node)
{
node.BaseProperty = this.MyBaseProperty;
foreach (var child in this.Children)
node.Children.Add(child.Commit());
}
}
class MyNodeA : MyNode
{
...
public override Node Commit()
{
var m = new NodeA(); // "factory" method for each type
this.Commit(m);
return m;
}
public override void Commit(Node node)
{
var m = (NodeA)node; // provoke InvalidCastException if coding error
base.Commit(node);
m.DerivedAProperty = this.MyDerivedAProperty;
}
}
I have used this approach multiple times successfully and I generally like it, because the methods that have to be added to the class are straight forward, and so is the external code. Also, it avoids code duplication by calling base.Load(node) / base.Commit(node). However, I really don't like that if/else ladder in the static Load factory method.
I would prefer to have a factory method in each type for the Node -> MyNode (Load) case, similar to how it is in the MyNode -> Node (Commit) case. But static and virtual is obviously a bit problematic. I would also prefer to not do the two casts I have to do now.
Is achieving such a thing somehow possible?
My recommendation would be to solve the problem incrementally. First you'll need something to traverse the tree and convert each node along the way:
public static class NodeExtensions
{
public static MyNode ToMy( this Node node )
{
var result = node.Transform();
result.Children = node.Children.Select( ToMy ).ToList();
}
public static Node FromMy( this MyNode node )
{
var result = node.Transform();
result.Children = node.Children.Select( ToMy ).ToList();
}
public static MyNode Transform( this Node node )
{
// TODO code to transform any single node here
}
public static Node Transform( this MyNode node )
{
// TODO code to transform any single node here
}
}
Since you mention that the transformation from Node to MyNode is not a simple matter of copying properties, yet also indicate that there will be a lot of that going on, my initial thought is that this is a task for AutoMapper.
AutoMapper lets you create a "conversion profile" that describes which properties to map and any special rules you want to apply to any given mapping. Also, it provides both generic and non-generic methods, so you can use it even if you do not know the types at compile-time. It is commonly used to convert between entities and view models, so you'll find plenty of questions and answers related to its usage elsewhere here.
Defining type maps basically consists of a number of calls like this:
Mapper.CreateMap<Node,MyNode>(); // no special rules for this map
You'll have to consule the AutoMapper documentation for the specifics about how to create special mappings, like splitting properties or performing type conversions. You'll also need to create maps going both ways in order to be able to map in either direction.
Once you have defined all of your mappings, the Transform extension methods can be as simple as:
public static MyNode Transform( this Node node )
{
return Mapper.Map( node.GetType(), node.GetMatchingMyType(), node );
}
public static Type GetMatchingType( this Node node )
{
// you can use a dictionary lookup or some other logic if this doesn't work
var typeName = "My" + node.GetType().Name;
return typeof(MyNode).Assembly.GetTypes().Single( t => t.Name == typeName );
}
When everything is in place, you can convert the entire tree by writing:
var myTree = node.ToMy();
// and back
node = myTree.FromMy();
Is everything as consistently named as you present above?
If so, you could build a set of generic convert-to convert-from functions that use reflection.
Here is what I'm thinking (this is stream of conciousness, not verified compiled code):
<T> ConvertTo<TMy, T>(TMy object)
{
// create an object of type T
T newObj = new T();
// iterate the members of T using reflection
foreach(member in T)
{
// find the equavalent My members in TMy
// transfer the data
}
return newObj;
}
I will look into this a bit more and possibly generate working code sometime this weekend.

How to work with nodes?

I'm building up a tree to parse some text, so I've created some nodes:
abstract class Node { }
class TextNode : Node
{
public readonly string Text;
public TextNode(string text)
{
Text = text;
}
public TextNode(char ch)
{
Text = ch.ToString();
}
}
class VariableNode : Node
{
public readonly string Name;
public VariableNode(string name)
{
Name = name;
}
}
I'm going to add some "branching" nodes pretty soon (nodes that contain other nodes).
I'm wondering about the best way to process them. Right now I've got some code that looks like this:
foreach (var item in nodes)
{
if (item is TextNode)
sb.Append(((TextNode)item).Text);
if (item is VariableNode)
sb.Append(dict[((VariableNode)item).Name]);
}
Which seems a bit clunky, and will only get worse as I add to it.
Should I
Try to encapsulate the logic into the base Node class somehow so that I can just the DoStuff() function without worrying about type-casting?
Should I add some kind of enum for each node type so that I can use a switch instead of a foreach loop?
Something else?
Need to give you guys a bit more context. In the example above, variables nodes need access to the dict to render themselves.
I'm parsing a template. In the template, there are variables. The variable names and their values are stored in the dict. At parse time, I don't have the values (well, I could, but I want to be able to re-render the template with different values), so I need to be able to pass in different dicts to the template. The way I have it set up, the template does all the rendering, the nodes do nothing. I guess I could pass the dict one more level down to each node so they can render themselves...
To elaborate on #1
// in class Template
public string Render(Dictionary<string, object> dict)
{
var sb = new StringBuilder();
foreach (var item in nodes)
sb.Append(item.Render(dict));
return sb.ToString();
}
interface INode {
string Render(Dictionary<string, object> dict);
}
class TextNode : INode
{
private string _text;
public TextNode(string text)
{
_text = text;
}
public TextNode(char ch)
{
_text = ch.ToString();
}
public string Render(Dictionary<string, object> dict)
{
return _text;
}
}
class VariableNode : INode
{
private string _name;
// TODO: filters...
public VariableNode(string name)
{
_name = name;
}
public string Render(Dictionary<string, object> dict)
{
return dict[_name].ToString();
}
}
I guess that isn't such a bad solution either.
Solutions so far:
Use an enum and switch
Build a dictionary of type/actions to make the switch a bit cleaner
Polymorphism (x2)
Visitor pattern (haven't read this yet)
Use ANTLR -- although ANTLR will build a tree and then this problem applies again
You can instead use an interface and define a enum property, for eg. NodeType Type where Type is an enum with values TextNode, VariableNode. Although, here also you will need to cast the node to get the value. You can try to add a property named Value which returns Text or Name depending on the NodeType. If dict is accessible from VariableNode, Value can return the exact value needed for your method.
All in all, I think interfaces suit your requirements better than an abstract class.
If you're going to have lots of different node types with different behaviours I would certainly consider using a base class Node and then implementing a specialized node class for each type that implements the specific behaviour.
An alternative to putting tree processing logic into the nodes is to use the visitor pattern. In this case you would tend to have a more homogeneous tree structure with the specific processing rules maintained outside the tree.
If this tree is for the purpose of parsing text have you looked at Antlr? This tool can generate your syntax tree for you, based on a specified grammar.
Move your foreach(var item in nodes) into a method (i.e. BuildAll) in the abstract node class, create an abstract / virtual method Build (in the abstract Node class) and call the method Build() in the BuildAll and let it output a string...
Like so:
public abstract string Build();
public string BuildAll() {
var output = new StringBuilder();
foreach(var node in nodes) {
output.append(node.Build());
}
return output.toString();
}
and override it inside each actual implementation of node...
so TextNode will have...
public override string Build() {
return ... extract whatever you want from TextNode;
}
In this case, your base class does not need to know the exact implementation of its descendant, thus does not break the Open Close Principle.
You can create a Dictionary<Type,Action<T>> - the keys are the node types and the Action<T> delegates are what you do with each.
You can than simply do:
Dictionary[typeof(variable)];
In order to execute the right action for each type.
Polymorphism is exactly what you want. Something like this:
class Node
{
public virtual string ToDisplayText(params object[] parameters)
{
return string.Empty;
}
}
class TextNode : Node
{
public override string ToDisplayText(params object[] parameters)
{
return this.Text;
}
}
class VariableNode : Node
{
public override string ToDisplayText(params object[] parameters)
{
//check parameters
var dict = (Dictionary<string,string>)parameters[0];
return dict[this.Name];
}
}
So you can:
foreach(var node in nodes)
{
sb.Append(node.ToDisplayText(dict));
}

Searching over a templated tree

So I have 2 interfaces:
A node that can have children
public interface INode
{
IEnumeration<INode> Children { get; }
void AddChild(INode node);
}
And a derived "Data Node" that can have data associated with it
public interface IDataNode<DataType> : INode
{
DataType Data;
IDataNode<DataType> FindNode(DataType dt);
}
Keep in mind that each node in the tree could have a different data type associated with it as its Data (because the INode.AddChild function just takes the base INode)
Here is the implementation of the IDataNode interface:
internal class DataNode<DataType> : IDataNode<DataType>
{
List<INode> m_Children;
DataNode(DataType dt)
{
Data = dt;
}
public IEnumerable<INode> Children
{
get { return m_Children; }
}
public void AddChild(INode node)
{
if (null == m_Children)
m_Children = new List<INode>();
m_Children.Add(node);
}
public DataType Data { get; private set; }
Question is how do I implement the FindNode function without knowing what kinds of DataType I will encounter in the tree?
public IDataNode<DataType> FindNode(DataType dt)
{
throw new NotImplementedException();
}
}
As you can imagine something like this will not work out
public IDataNode<DataType> FindNode(DataType dt)
{
IDataNode<DataType> result = null;
foreach (var child in Children)
{
if (child is IDataNode<DataType>)
{
var datachild = child as IDataNode<DataType>;
if (datachild.Data.Equals(dt))
{
result = child as IDataNode<DataType>;
break;
}
}
else
{
// What??
}
// Need to recursively call FindNode on the child
// but can't because it could have a different
// DataType associated with it. Can't call FindNode
// on child because it is of type INode and not IDataNode
result = child.FindNode(dt); // can't do this!
if (null != result)
break;
}
return result;
}
Is my only option to do this when I know what kinds of DataType a particular tree I use will have? Maybe I am going about this in the wrong way, so any tips are appreciated. Thanks!
First of all, you need to put the FindNode method in INode. Otherwise, you cannot find a node of some type DataType... before having found a node of type DataType. Even if you have a reference to an object that you know is a DataNode<X>, this won't help you if someone tells you to find a DataNode<Y>.
There are now two roads you may take: if you want DataNode to be templated, then you need to know all possible types of data in the tree at compile time. If you know that, you can use a generic DataNode. If there's a chance that you may want to find a node with data of some type that will only become known to you at runtime (e.g. from the return value of some method that you do not control) then you cannot use generics.
I will illustrate the generic solution below.
public interface INode
{
IEnumerable<INode> Children { get; }
IDataNode<DataType> FindNode<DataType>(DataType value);
void AddChild(INode node);
}
public interface IDataNode<DataType> : INode
{
DataType Data { get; }
}
INode.FindNode could be implemented like this:
public IDataNode<DataType> FindNode<DataType> (DataType value) {
// If we are searching for ourselves, return this
var self = this as IDataNode<DataType>;
if (self != null && self.Data.Equals(value)) {
return self;
}
// Otherwise:
// 1. For each of our children, call FindNode on it. This will
// find the target node if it is our child, since each child
// will check if it is the node we look for, like we did above.
// 2. If our child is not the one we are looking for, FindNode will
// continue looking into its own children (depth-first search).
// 3. Return the first descendant that comes back and is not null.
// If no node is found, FirstOrDefault means we will return null.
return this.children.Select(c => c.FindNode(value))
.FirstOrDefault(found => found != null);
}
I have to say that the above recursive implementation with LINQ tries perhaps to be too clever and is maybe not very easy to understand. It could always be written with foreach, to make it more clear.
Use a Generic Function:
public IDataNode<DataType> FindNode<DataType>(DataType dt)
{
IDataNode<DataType> result = null;
foreach (var child in Children)
{
if (child is IDataNode<DataType>)
{
var datachild = child as IDataNode<DataType>;
if (datachild.Data.Equals(dt))
{
result = child as IDataNode<DataType>;
break;
}
}
else
{
// it's not a DataType You're looking for, so ignore it!
}
}
return result;
}
Then you call it like this:
var resultsStr = tree.FindNode<string>("Hello");
var resultsInt = tree.FindNode<int>(5);
var resultsCust = tree.FindNode<MyCustomClass>(new MyCustomClass("something"));

Categories