I am using Roslyn and I have created an AST walker in order to detect when certain nodes are traversed.
The source I am trying to parse is the following:
var source = string.Format(#"
using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace HelloWorld
{{
class {0} : {1}
{{
static void Main(string[] args)
{{
Console.WriteLine(""Hello, World!"");
}}
}}
}}", "MyClass", "MyBaseClass");
And this is the walker:
namespace MyStuff
{
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
public class MyWalker : CSharpSyntaxWalker
{
public MyWalker(SyntaxNode node) :
base(SyntaxWalkerDepth.StructuredTrivia)
{
this.Root = node;
}
public SyntaxNode Root { get; private set; }
public void Start()
{
this.Visit(this.Root);
}
sealed public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node)
{
this.DoSomething(node, this.type.IsInstanceOfType(node));
}
...
sealed public override void VisitYieldStatement(YieldStatementSyntax node)
{
this.DoSomething(node, this.type.IsInstanceOfType(node));
}
// BREAKPOINT IN THE BODY OF THIS FUNCTION!
private void DoSomething(SyntaxNode node)
{
...
}
}
}
I am overriding all visit methods, alphabetically from VisitAccessorDeclaration to VisitYieldStatement. I am doing this just to try stuff, not for real applications, I know it is quite nonsense.
Visiting
I run it:
SyntaxNode root = CSharpSyntaxTree.ParseText(source).GetRoot();
And then run the walker:
var astWalker = new MyWalker(this.Root);
astExecutor.Start();
// NEXT OPERATION
What happens? I seta breakpoint on function DoSomething and I expect it to be it a lot of times. Actually it does not happen. It happens only for one node: VisitCompilationUnit. After the control flow passes on on // NEXT OPERATION and that's it.
What am I missing? Thanks
In your overrides, you need to call the base version of the method you are overriding. We allow you to stop the walk. By not calling base so that if you are trying to visit only specific nodes, you can control it.
Related
simple code here and the answers I find don't seem to work.
I'm using
SharpDevelop Version : 3.2.1.6466
.NET Version : 2.0.50727.5485
The problem is the error code
Expected class, delegate, enum, interface, or struct (CS1518).
Any ideas?
Program.cs codes:
using System;
using System.Threading;
namespace Threshold
{
public class Class1
{
public Class1()
{
Heritage YOLO = new Heritage();
YOLO.Fractal();
}
}
static void Main()
{
//do nothing
}
}
The cs file it calls is:
using System;
using System.Threading;
namespace Threshold
{
public class Heritage
{
int Fractal()
{
//Do stuff.
}
}
internal partial class DefineConstants
{
public const string DRIVERPATH = "d:\\tc\\bgi";
}
}
Please help with a fix.
Thanks.
Your main method is outside the class. Put it inside.
I'm attempting to extend my custom classes and running into a problem where it cannot find the extension method.. I have and can extend any built in classes or even ones contained within DLL's. I don't know if this is a compilation error or if I'm doing something wrong. Threw together a small program for an example, won't compile..
Here's the extension:
namespace ExtensionMethodTesting.Extension
{
public static class Extension
{
public static void DoSomething(this ExtensionMethodTesting.Blah.CustomClass r)
{
}
}
}
Here's the Custom Class:
namespace ExtensionMethodTesting.Blah
{
public class CustomClass
{
public static void DoNothing()
{
}
}
}
Here's the code calling it:
using ExtensionMethodTesting.Blah;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ExtensionMethodTesting.Extension;
namespace ExtensionMethodTesting
{
class Program
{
static void Main(string[] args)
{
CustomClass.DoNothing();
CustomClass.DoSomething();
}
}
}
I must be missing something... Anyways the exact error just for clarification is:
Error 1 'ExtensionMethodTesting.Blah.CustomClass' does not contain a definition for 'DoSomething' c:\users\damon\documents\visual studio 2013\Projects\ExtensionMethodTesting\ExtensionMethodTesting\Program.cs 16 25 ExtensionMethodTesting
Extension methods require an instance of an object. You'll have to new up a CustomClass to use it.
var custom = new CustomClass();
custom.DoSomething();
See this answer as to why that is.
You need to instantiate an object of the CustomClass to use its extension method.
CustomClass obj = new CustomClass();
obj.DoSomething();
I have a class:
namespace FooIOS
{
public class Foo
{
public static void doThis() {...}
}
}
And this works:
using FooIOS;
namespace Sample.iOS
{
public void method () {
Foo.doThis();
}
}
However, this does not work the same way when I change the namespace to insert a period:
namespace Foo.iOS
{
public class Foo
{
public static void doThis() {...}
}
}
using Foo.iOS;
namespace Sample.iOS
{
public void method () {
// Compilation error
Foo.doThis();
// Compilation error
Foo.iOS.doThis()
// This works but I can't have it that long and complicated (I'm writing an API call)
Foo.iOS.Foo.doThis();
}
}
I'm pretty inexperienced with C# and I'm wondering if there's any way to use the period in the namespace and not deal with the complicated call.
namespace Foo.iOS
{
public class Foo
{
public static void doThis() {...}
}
}
Your namespace name is Foo.iOS, class name is Foo, static method name is doThis(). The fully qualified path to access that method is NAMESPACE.CLASS.METHOD_NAME, so it becomes:
Foo.iOS.Foo.doThis();
Here is nothing wrong with C#, but with the naming you use.
From this a couple of suggestions:
try to no use . inside names of the namespace, as this introduces confusion
try to not name namespace as the class inside it, as this introduces confusion.
I'm pretty inexperienced with C# and I'm wondering if there's any way
to use the period in the namespace and not deal with the complicated
call.
Short answer is: name your namespaces, classes and member functions in a way, that it does not look complicated to you and to others.
EDIT
Consider that you can use also Namespace Alias.
For example:
using IOS = Foo.iOS;
...
IOS.Foo.doThis();
But as I said before, it's better to avoid . in namespace name at first place.
Bring the using Foo.iOS; statement inside the namespace Sample.iOS namespace block, like shown below, then you will be able to call doThis() like in your 1st attempt Foo.doThis(); that was previously giving you a compile error.
namespace Sample.iOS
{
using Foo.iOS;
public void method () {
// this works
Foo.doThis();
}
}
Related reading: Inside or Outside? by Eric Lippert on MSDN.
Fully working Code sample:
Create a new Console App in Visual Studio, and then in the Program.cs class, delete all lines, paste the following, do a compile and then run.
using System;
namespace Foo.iOS
{
public class Foo
{
public static void doThis() { Console.Write("Inside doThis");}
}
}
namespace Sample.iOS
{
using Foo.iOS;
class Program
{
static void Main(string[] args)
{
method();
Console.ReadKey();
}
public static void method ()
{
// works fine
Foo.doThis();
}
}
}
I want to access certain form elements from classes that normally don't have access to them. Allow me to illustrate the problem.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Collections;
namespace MyApp {
public partial class MyApp : Form
{
public MyApp()
{
InitializeComponent();
// Code
}
public void updateLabel(string message)
{
myLabel.Text = message;
}
}
public class NewClass
{
public NewClass()
{
// I want to call updateLabel("My message") here, but 'MyApp.updateLabel("My message");' didn't work even though I made updateLabel public
}
}
}
How do I tackle this issue? I'm relatively new to C#, but I have experience with C, PHP, Java and JavaScript. I'm using Visual C# 2010 Express.
You need to pass the instance of the MyApp class to the NewClass class.
You can then call UpdateLabel on the MyApp instance, without making the label public.
Since updateLabel is a non-static member method in MyApp, you need to create an instance of MyApp before calling any of its instance methods.
use following line of code inside NewClass ctor:
MyApp myapp = new MyApp();
myapp.updateLabel("Hello World");
I assume MyApp class is already instantiated, in which case you have to pass the reference to NewClass (may be over constructor) as SLaks already mentioned.
May be technique below will be helpfull. It may use Action's or Func's:
[Test]
public void ActionsTest()
{
var parent = new Parent();
parent.Child.RaiseCallFromParent();
parent.Child.RaiseCallInParent();
}
public class Parent
{
private readonly Child _child = new Child();
public Parent()
{
Child.ActionToCallMethodFromParent = methodCalledFromChild;
Child.ActionToBeCalledInParent += actionCalledInParent;
}
public Child Child
{
get { return _child; }
}
private void actionCalledInParent()
{
Console.WriteLine("It is called in parent on child initiative.");
}
private void methodCalledFromChild()
{
Console.WriteLine("It is called from child");
}
}
public class Child
{
public Action ActionToCallMethodFromParent;
public Action ActionToBeCalledInParent;
public void RaiseCallFromParent()
{
//This works in cases when you need to consume something from Parent but here you cannot take it directly
if (ActionToCallMethodFromParent != null)
ActionToCallMethodFromParent();
}
public void RaiseCallInParent()
{
//This works like an event
if (ActionToBeCalledInParent != null)
ActionToBeCalledInParent();
}
}
Here's my own proposed solution. I pass the myLabel as a parameter to the class constructor that needs access to the label, like so:
The call:
NewClass newClassObj = new NewClass(myLabel);
The class:
public class NewClass
{
public NewClass(Label myLabel)
{
myLabel.Text = "Hello world!";
}
}
Unless this a bad programming practice, I'd prefer this solution. Thoughts?
Its probably better to raise an event from your own class then catch it in the form and update the controls from there, then you are not connecting your logic to specific UI elements.
Change public void updatelabel(string message) to public static void updatelabel(string message).
Then from new class you would access it like myapp.updatelabel(message).
You would of have to add using myapp to top of new class.
This may be an ignorant question, but I'm unsure why I can not use namespace aliasing and extension methods together.
The following example works just fine:
Program.cs
using System;
using ExtensionMethodTest.Domain;
namespace ExtensionMethodTest
{
class Program
{
static void Main(string[] args)
{
var m = new Domain.MyClass();
var result = m.UpperCaseName();
}
}
}
MyClass.cs
using System;
namespace ExtensionMethodTest.Domain
{
public class MyClass
{
public string Name { get; set; }
}
}
MyClassExtensions.cs
using System;
namespace ExtensionMethodTest.Domain
{
public static class MyClassExtensions
{
public static string UpperCaseName (this MyClass myClass)
{
return myClass.Name.ToUpper();
}
}
}
However, when I alias domain as follows in Program.cs:
using Domain = ExtensionMethodTest.Domain;
The extension method no longer works..
This can be rather frustrating when I'm dealing with converting various domain objects to contract objects (let's say I have 4 domain assemblies and 4 contract assemblies) for use in a web service. Using aliasing would be very handy as I could alias as follows and continue to use the various extension methods (such as ToContract, etc.):
using BillingContracts = Namespace.Billing.Contracts;
using IssuingContracts = Namespace.Issuing.Contracts;
etc...
I look forward to the answer.. I'm sure it's straight forward, but I, for the life of me, can't figure out why it doesn't work.
Thanks!
Make sure to still add a non-aliased using statement:
Program.cs
using System;
using ExtensionMethodTest.Domain; //DON'T FORGET A NON-ALIASED USING
using MyDomain = ExtensionMethodTest.Domain;
namespace ExtensionMethodTest
{
class Program
{
static void Main(string[] args)
{
var m = new MyDomain.MyClass();
var result = m.UpperCaseName();
}
}
}
MyClass.cs
using System;
namespace ExtensionMethodTest.Domain
{
public class MyClass
{
public string Name { get; set; }
}
}
MyClassExtensions.cs
using System;
namespace ExtensionMethodTest.Domain
{
public static class MyClassExtensions
{
public static string UpperCaseName (this MyClass myClass)
{
return myClass.Name.ToUpper();
}
}
}
I also love to use namespace aliasing but its not working in case of Extension methods. So one thing that i did is, I changed the namespace of extension class to same namespace that my main project has (although my extension class resides in sub folder of main project).
Suppose I have a project myFirstProj which surely has namespace myFirstProj for root classes. My extension class is present in myFirstProj/Common/myExtensionClass with contains namespace myFirstProj.Common { //myExtensionClass }.
So now what I did is, I changed the namespace of myExtensionClass from namespace myFirstProj.Common{ //myExtensionClass } to namespace myFirstProj{ //myExtensionClass } .
Now i can use my extension methods in my whole project myFirstProj event without specifying using statement for my extension class.
I know this isn't a standard way to that but I haven't found any other workaround for it expect this one because for my Project there is a requirement to go with namespace aliasing for project namespaces.