I want to detect class from a string.
example;
string test = "class Test { string Name; string PassWord;}"
string[] classNames = GetClassNamesFromString(test);
//Now string[0] has to be Test
Or more complex
string test = "[Export(typeof(ITest))]public class Test : ITest { }"
string[] classNames = GetClassNamesFromString(test);
//Now string[0] has to be Test
And must be work with generics.
I would simple use a Regex.
class\s+(\w+\d*)+
In that maner:
string test = "[Export(typeof(ITest))]public class Test : ITest { }";
var match = Regex.Match(test, #"class\s+(\w+\d*)+");
string classname = match.Value.Split(new []{' '}, StringSplitOptions.RemoveEmptyEntries)[1];
It even works with lots of space between class and the name:
string test = "[Export(typeof(ITest))]public class Test : ITest { }";
Try this:
var input = "public class MyClass {//whatever}";
var regex = new Regex(#"class\s(\w+)\s*[{,:]", RegexOptions.Compiled);
var result = regex.Match(input);
var className = result.Groups[1].Value;
If running this multiple times, use the RegexOptions.Compiled and store the regex in an instance variable to get better performance, otherwise you can remove the flag.
I let you take care of the error handling and don't forget to write some test conditions etc I have not added support for generics I also leave that to you to explore the awesomeness of REGEX.
I solved this way;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
var t = CSharpSyntaxTree.ParseText(#"
using System;
namespace Muhterem
{
class Main
{
static void Main(string[] args)
{
Hello();
}
static void Hello()
{
Console.WriteLine();
}
}
class Generic<T>
{}
abstract class AbstractClass
{}
}
");
var roo = t.GetRoot();
var classes = roo.DescendantNodes().OfType<ClassDeclarationSyntax>();
foreach (var y in classes)
{
Console.WriteLine(y.Identifier);
}
and output ;
Related
Using the Roslyn API with Visual Studio 2015, can I convert an object instance to source code? Can I create an extension method like ".ToSourceCode()" as shown below?
class Foo { }
class Program
{
static string classSourceCode = "class Foo { }";
static void Main()
{
var instance = new Foo();
var instanceSourceCode = instance.GetType().ToSourceCode();
System.Diagnostics.Debug.Assert(instanceSourceCode == classSourceCode);
}
}
No. However, ILSpy can.
Based on the comments on the question and what I understand about Roslyn, decompilation is not supported. However, thanks to #Bradley's ILSpy tip, there is a solution:
Download the ILSpy binaries from http://ilspy.net/
Reference the following assemblies: ICSharpCode.Decompiler.dll, ILSpy.exe, Mono.Cecil.dll, ILSpy.BamlDecompiler.Plugin.dll
Implement the ".ToSourceCode()" extension method as shown below:
using System;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy;
using Mono.Cecil;
class Foo { }
class Program
{
static string classSourceCode = "using System; internal class Foo { } ";
static void Main()
{
var instance = new Foo();
var instanceSourceCode = instance.GetType().ToSourceCode();
System.Diagnostics.Debug.Assert(instanceSourceCode == classSourceCode);
}
}
static class TypeExtensions
{
public static string ToSourceCode(this Type source)
{
var assembly = AssemblyDefinition.ReadAssembly(Assembly.GetExecutingAssembly().Location);
var type = assembly.MainModule.Types.FirstOrDefault(t => t.FullName == source.FullName);
if (type == null) return string.Empty;
var plainTextOutput = new PlainTextOutput();
var decompiler = new CSharpLanguage();
decompiler.DecompileType(type, plainTextOutput, new DecompilationOptions());
return Regex.Replace(Regex.Replace(plainTextOutput.ToString(), #"\n|\r", " "), #"\s+", " ");
}
}
I know I can test the condition and run the code like this:
if (scrapedElement.Contains(".html")
string [] Test = new string[] { scrapedElement, string.empty }
else
string [] Test = new string[] { scrapedElement }
However, I want to do it in a single line if possible. Something similar to this (this is the full line of code that I want it to work in):
File.AppendAllLines(#"C:\Users\DJB\Documents\Visual Studio 2017\Projects\TempFiles\WebScraperExport.csv", new[] { (scrapedElement.Contains(".html") ? scrapedElement, string.Empty : scrapedElement)});
What I am doing is a web scraper that then saves the files in an excel file. For every element it finds that is a link, add a blank line after it, if not just add the element.
This compiled for me and should do what You need
using System;
public class Test
{
public static void Main()
{
string scrapedElement = "test test .html test";
string [] Test = scrapedElement.Contains(".html")
? new string[] { scrapedElement, string.Empty }
: new string[] { scrapedElement };
}
}
Another alternative that will handle Your case without duplication (but not 1-liner!)
using System;
public class Test
{
public static void Main()
{
string scrapedElement = "test test .html test";
string [] Test =new string[scrapedElement.Contains(".html")?2:1];
Test[0] = scrapedElement;
}
}
How would I automate the creation of a default implementation of a class from an interface using conventions. In other words, if I have an interface:
public interface ISample
{
int SampleID {get; set;}
string SampleName {get; set;}
}
Is there a snippet, T4 template, or some other means of automatically generating the class below from the interface above? As you can see, I want to put the underscore before the name of the field and then make the field the same name as the property, but lower-case the first letter:
public class Sample
{
private int _sampleID;
public int SampleID
{
get { return _sampleID;}
set { _sampleID = value; }
}
private string _sampleName;
public string SampleName
{
get { return _sampleName;}
set { _sampleName = value; }
}
}
I am not sure if T4 would be the easiest solution here in terms of readability but you can also use another code generation tool at your disposal: the CodeDom provider.
The concept is very straightforward: code consists of building blocks that you put together.
When the time is ripe, these building blocks are then parsed into the language of choice . What you end up with is a string that contains the source code of your newly created program. Afterwards you can write this to a textfile to allow for further use.
As you have noticed: there is no compile-time result, everything is runtime. If you really want compiletime then you should use T4 instead.
The code:
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
using System.Reflection;
using System.Text;
namespace TTTTTest
{
internal class Program
{
private static void Main(string[] args)
{
new Program();
}
public Program()
{
// Create namespace
var myNs = new CodeNamespace("MyNamespace");
myNs.Imports.AddRange(new[]
{
new CodeNamespaceImport("System"),
new CodeNamespaceImport("System.Text")
});
// Create class
var myClass = new CodeTypeDeclaration("MyClass")
{
TypeAttributes = TypeAttributes.Public
};
// Add properties to class
var interfaceToUse = typeof (ISample);
foreach (var prop in interfaceToUse.GetProperties())
{
ImplementProperties(ref myClass, prop);
}
// Add class to namespace
myNs.Types.Add(myClass);
Console.WriteLine(GenerateCode(myNs));
Console.ReadKey();
}
private string GenerateCode(CodeNamespace ns)
{
var options = new CodeGeneratorOptions
{
BracingStyle = "C",
IndentString = " ",
BlankLinesBetweenMembers = false
};
var sb = new StringBuilder();
using (var writer = new StringWriter(sb))
{
CodeDomProvider.CreateProvider("C#").GenerateCodeFromNamespace(ns, writer, options);
}
return sb.ToString();
}
private void ImplementProperties(ref CodeTypeDeclaration myClass, PropertyInfo property)
{
// Add private backing field
var backingField = new CodeMemberField(property.PropertyType, GetBackingFieldName(property.Name))
{
Attributes = MemberAttributes.Private
};
// Add new property
var newProperty = new CodeMemberProperty
{
Attributes = MemberAttributes.Public | MemberAttributes.Final,
Type = new CodeTypeReference(property.PropertyType),
Name = property.Name
};
// Get reference to backing field
var backingRef = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), backingField.Name);
// Add statement to getter
newProperty.GetStatements.Add(new CodeMethodReturnStatement(backingRef));
// Add statement to setter
newProperty.SetStatements.Add(
new CodeAssignStatement(
new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), backingField.Name),
new CodePropertySetValueReferenceExpression()));
// Add members to class
myClass.Members.Add(backingField);
myClass.Members.Add(newProperty);
}
private string GetBackingFieldName(string name)
{
return "_" + name.Substring(0, 1).ToLower() + name.Substring(1);
}
}
internal interface ISample
{
int SampleID { get; set; }
string SampleName { get; set; }
}
}
This produces:
Magnificent, isn't it?
Sidenote: a property is given Attributes = MemberAttributes.Public | MemberAttributes.Final because omitting the MemberAttributes.Final would make it become virtual.
And last but not least: the inspiration of this awesomeness. Metaprogramming in .NET by Kevin Hazzard and Jason Bock, Manning Publications.
My aim is to "Sanitize a string".
The class should do:
trim an input
make the first letter upper case.
Could you please tell me:
Is there a way to better code it?
Would it make sense to use a PARAMETER for a method like: CapitalizeFirstLetterTrim(string x)
when I initiate an object I need write a lot of code like below, any other way to make it shorter?
UserInputSanitizer myInput = new UserInputSanitizer();
myInput.Input = " ciao world";
string ouput = myInput.CapitalizeFirstLetterTrim();
Useful resource http://msdn.microsoft.com/en-us/library/bb311042.aspx
----------- CLASS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WebProject.Core.Utilities
{
public class UserInputSanitizer
{
// Backing variables
private string _input;
// Properties
public string Input
{
set { _input = value; }
}
private string _output;
// Backing variables
// Properties
public string Output
{
get { return _output; }
}
public string CapitalizeFirstLetterTrim()
{
// Trim
_input.Trim();
// Make First letter UpperCase and the rest levae lower case
_output = _input.Substring(0, 1).ToUpper() + _input.Substring(1);
return Output;
}
}
}
I think I would create an extension method on string instead:
public static class MyStringExtensions{
public static string Sanitize(this string input)
{
if(input == null) throw new ArgumentNullException("input");
var trimmed = input.Trim();
return System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(trimmed);
}
}
You would call the method like this:
var s = " Unsanitized ";
var sanitized = s.Sanitize();
You can use Extension Method to support your requirement
With extension methods , you can use method as if they are part of System.String class.
See Here
I would use an extension method for the string class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WebProject.Core.Utilities
{
public static class StringExtensions
{
public static string Sanitize(this string s)
{
//your code to sanitize your string, for example
if(s == null) throw new ArgumentNullException("s");
var trimmed = input.Trim();
return System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(trimmed);
}
}
}
Then you can use:
string s = " UnsanitizedString";
s = s.Sanitize();
I would make the class and methods static
namespace WebProject.Core.Utilities
{
public static class UserInputSanitizer
{
public static string CapitalizeFirstLetterTrim(string input)
{
// Trim
input.Trim();
// Make First letter UpperCase and the rest levae lower case
return input.Substring(0, 1).ToUpper() + input.Substring(1);
}
}
}
and then you would call it like this:
string ouput = UserInputSanitizer.CapitalizeFirstLetterTrim(" ciao world");
Rather than a utility class, it may make more intuitive sense to write this as an extension method for string so you can just call it directly from the literal. Much less overhead.
I want to create an instance of an IronPython class from C#, but my current attempts all seem to have failed.
This is my current code:
ConstructorInfo[] ci = type.GetConstructors();
foreach (ConstructorInfo t in from t in ci
where t.GetParameters().Length == 1
select t)
{
PythonType pytype = DynamicHelpers.GetPythonTypeFromType(type);
object[] consparams = new object[1];
consparams[0] = pytype;
_objects[type] = t.Invoke(consparams);
pytype.__init__(_objects[type]);
break;
}
I am able to get the created instance of the object from calling t.Invoke(consparams), but the __init__ method doesn't seem to be called, and thus all the properties that I set from my Python script aren't used. Even with the explicit pytype.__init__ call, the constructed object still doesn't seem to be initialised.
Using ScriptEngine.Operations.CreateInstance doesn't seem to work, either.
I'm using .NET 4.0 with IronPython 2.6 for .NET 4.0.
EDIT: Small clarification on how I'm intending to do this:
In C#, I have a class as follows:
public static class Foo
{
public static object Instantiate(Type type)
{
// do the instantiation here
}
}
And in Python, the following code:
class MyClass(object):
def __init__(self):
print "this should be called"
Foo.Instantiate(MyClass)
The __init__ method never seems to be called.
This code works with IronPython 2.6.1
static void Main(string[] args)
{
const string script = #"
class A(object) :
def __init__(self) :
self.a = 100
class B(object) :
def __init__(self, a, v) :
self.a = a
self.v = v
def run(self) :
return self.a.a + self.v
";
var engine = Python.CreateEngine();
var scope = engine.CreateScope();
engine.Execute(script, scope);
var typeA = scope.GetVariable("A");
var typeB = scope.GetVariable("B");
var a = engine.Operations.CreateInstance(typeA);
var b = engine.Operations.CreateInstance(typeB, a, 20);
Console.WriteLine(b.run()); // 120
}
EDITED according to clarified question
class Program
{
static void Main(string[] args)
{
var engine = Python.CreateEngine();
var scriptScope = engine.CreateScope();
var foo = new Foo(engine);
scriptScope.SetVariable("Foo", foo);
const string script = #"
class MyClass(object):
def __init__(self):
print ""this should be called""
Foo.Create(MyClass)
";
var v = engine.Execute(script, scriptScope);
}
}
public class Foo
{
private readonly ScriptEngine engine;
public Foo(ScriptEngine engine)
{
this.engine = engine;
}
public object Create(object t)
{
return engine.Operations.CreateInstance(t);
}
}
I think I solved my own question -- using the .NET Type class seems to have discarded Python type information.
Replacing it with IronPython.Runtime.Types.PythonType works quite well.
Looks like you're looking for the answer given to this SO question.