I'm trying to extract a complete method which is inside a cs file.
for instance.. suppose we have a class like this...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GetMethodNm
{
class MyClass
{
public int ComplexMethod(int param1, int myCustomValue)
{
if (param1 == myCustomValue)
{
return 54;
}
else
{
return 0;
}
}
public string ComplexMethodV(int param1, int myCustomValue)
{
if (param1 < myCustomValue)
{
return "300";
}
else
{
return "My custom value to return";
}
}
public bool ComplexMethodX(int param1, int myCustomValue)
{
if (param1 == myCustomValue)
{
return true;
}
else
{
return false;
}
}
}
}
Then I need to extract the method reading the cs file ComplexMethodV .. How can I do this? I have tried with reflection but I can only get the name and some things inside of it.. but I would need the literal method within.
Using Roslyn tasks like this are relitively easy. In a project add the NuGet package Microsoft.CodeAnalysis.CSharp, then just use the following code
using System;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace SandboxConsole
{
class Program
{
public static void Main()
{
var text = File.ReadAllText("MyClass.cs");
var tree = CSharpSyntaxTree.ParseText(text);
var method = tree.GetRoot().DescendantNodes()
.OfType<MethodDeclarationSyntax>()
.First(x => x.Identifier.Text == "ComplexMethodV");
Console.WriteLine(method.ToFullString());
Console.ReadLine();
}
}
}
This outputs the text
public string ComplexMethodV(int param1, int myCustomValue)
{
if (param1 < myCustomValue)
{
return "300";
}
else
{
return "My custom value to return";
}
}
See the Wiki for more advanced tutorials on how to do things like parse entire solutions.
Related
So I'm trying to retrieve data from a database to display it in a table.
(This is a WebApi project). The idea is to go through all the prodactivity from the table whose status is 1. Put them in some list and return it.
To do this, I need to convert a TBL object to DAL. but here I am stuck. It is unable to perform a conversion and is therefore unwilling to return an object of a different type.
I tried to convert in all sorts of ways but it'S out of sync with the type in the controller.
This is my code: (do'nt look at the other functions. Look at the function getProductivityRequest at the end)
UserController.cs
using BL;
using DTO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;
namespace WebApiSystem.Controllers
{
[EnableCors(origins: "*", headers: "*", methods: "*")]//SupportsCredentials = true
[RoutePrefix("api/User")]
public class UserController : ApiController
{
[HttpGet]
[Route("login/{email}/{pass}")]
public IHttpActionResult LogIn(string email, string pass)
{
UserDTO user = BL.UserService.LogIn(email, pass);
if (user != null)
return Ok(user);
return NotFound();
}
[Route("register")]
public IHttpActionResult Register(UserDTO user)
{
return NotFound();
}
[HttpPost]
[Route("productivity")]
public IHttpActionResult InsertProductivity([FromBody] ProductivityDTO p)
{
bool b = BL.UserService.InsertProductivity(p);
if (b)
return Ok(b);
return BadRequest();
}
[HttpGet]
[Route("getProductivityRequest")]
public IHttpActionResult GetProductivityRequest()
{
return Json(BL.UserService.GetProductivityRequest());
}
}
}
UserService.cs
using DAL;
using DTO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BL
{
public class UserService
{
public static UserDTO LogIn(string email, string pass)
{
using (Model2 db = new Model2())
{
UserTbl user = db.UserTbl.FirstOrDefault(u => u.UserEmail == email && u.UserPassLogin == pass);
if (user == null)
return null;
return CONVERTERS.UserConverter.ConvertUsertoDTO(user);
}
}
public static bool InsertProductivity(ProductivityDTO p)
{
using (Model2 db = new Model2())
{
//conver dal to dto
ProductivityTbl prod = BL.CONVERTERS.ProductivityConverter.ProductivityDal(p);
prod.ProductivityStatus = 1;
db.ProductivityTbl.Add(prod);
db.SaveChanges();
return true;
}
return false;
}
public static ProductivityDTO GetProductivityRequest()//Here I can not convert
{
using (Model2 db = new Model2())
{
List<ProductivityDTO> PList = new List<ProductivityDTO>();
foreach (var item in db.ProductivityTbl.ToList())
{
if(item.ProductivityStatus==1)
{
ProductivityDTO prod = BL.CONVERTERS.ProductivityConverter.ConvertProductivitytoDTO(item);
PList.Add(prod);
}
}
return (PList);//He's unable to return the object
}
}
}
}
ProductivityConverter.cs(if it's relevant...)
using DTO;
using DAL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BL.CONVERTERS
{
class ProductivityConverter
{
public static ProductivityDTO ConvertProductivitytoDTO(ProductivityTbl productivity) {
return new ProductivityDTO
{
ProductivyCode = productivity.ProductivyCode,
ProductivityNum = productivity.ProductivityNum,
ProductivityStatus = productivity.ProductivityStatus,
UserCode = productivity.UserCode,
Cmment = productivity.Cmment,
Date = productivity.Date
};
}
public static ProductivityTbl ProductivityDal(ProductivityDTO productivity)
{
return new ProductivityTbl
{
ProductivyCode = productivity.ProductivyCode,
ProductivityNum = productivity.ProductivityNum,
ProductivityStatus = productivity.ProductivityStatus,
UserCode = productivity.UserCode,
Cmment = productivity.Cmment,
Date = productivity.Date
};
}
}
}
If anyone knows of another way to transfer the data I would love ideas.
Thanks!
Your method returns a ProductivityDTO:
public static ProductivityDTO GetProductivityRequest()
...but you are trying to return PList which is a List<ProductivityDTO>.
Your method signature should be:
public static List<ProductivityDTO> GetProductivityRequest()
Although your comment suggests you can't change the method signature. In which case you need to return just one DTO. How you determine which one is up to you. But if it were just one with a ProductivityStatus of 1 then you could do:
public static ProductivityDTO GetProductivityRequest()//Here I can not convert
{
using (Model2 db = new Model2())
{
return BL.CONVERTERS.ProductivityConverter.ConvertProductivitytoDTO(db.ProductivityTbl.FirstOrDefault(p => p.ProductivityStatus == 1)));
}
}
Your function is defined to return a single ProductivityDTO.
But your function is building a List<ProductivityDTO> and returning that.
Change your function return type to a collection type, such as:
public static List<ProductivityDTO> GetProductivityRequest()
or
public static IEnumerable<ProductivityDTO> GetProductivityRequest()
I found that with long.Parse, ToString can take argument and I can format it to desired string, for example.
Input:
Console.WriteLine(long.Parse("123").ToString("#-#-#"));
Output:
1-2-3
I wanted to do something similar with string, lets say I wanna parse string to format ####-###-####. Is there any way to do it without regex with one liner like example above?
EDIT
Ok, so I may be misunderstood, I didn't want to parse numbers, but string instead. I can do in python like:
'{}-{}-{}'.format(*'abc') and I will receive a-b-c. In C# it seems to work only with numbers.
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Globalization;
using System.Text;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello, world!");
Console.WriteLine("helloWorld".ToPhoneNumber("###-###-####"));
}
}
public static class AdvancedFormatString
{
public static string ToPhoneNumber(this string strArg, string outputformat)
{
if (outputformat == null)
return strArg;
var sb = new StringBuilder();
var i = 0;
foreach (var c in outputformat)
{
if (c == '#')
{
if (i < strArg.Length)
{
sb.Append(strArg[i]);
}
i++;
}
else
{
sb.Append(c);
}
}
return sb.ToString();
}
}
}
I have a basic WinForm Solution (MS VS2013, .Net framework 4.5) for test some methods included in a Dll, using Reflection. My goal is test the main application that it can run two methods of Dll (without referencing the dll in project), and later, run four methods (2 methods added) without stop the main application and run it again, using reflection.
Reflections works fine (if I stop the main application, replacing the dll file and run the main application again, all works fine), but I can't replace the dll at runtime.
The main application has a Timer control with an interval of 60 seconds. Every 60 seconds, a method is executed that checks if a DLL file is in a folder. If a DLL file exists in that folder, I want to use the new DLL in the main application (running) because the new DLL contains old methods (first DLL) and additional methods that the main application needs.
However, I am getting an error that the file is in use.
I have read several posts, questions, answers, MEF documentation, AppDomains related, but I have been unable to concatenate the information to be able to implement a solution.
Actually, I thought a lot before post this question, but I confess that I prefer to spend a moment of shame, knowing that you can give me a hand.
It would be for me a great help if you help me with code and specific instructions.
This is the code:
Main application:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
namespace testDLLs
{
public partial class Principal : Form
{
public Principal()
{
InitializeComponent();
}
private void Principal_Load(object sender, EventArgs e)
{
labelVersionDll.Text = metodosApoyo.RunDLLFunction("VersionOperaciones");
string cListaOperaciones = metodosApoyo.RunDLLFunction("ListaOperaciones");
string[] aOperaciones = cListaOperaciones.Split('|');
comboBoxOperaciones.Items.Clear();
foreach (string cOperacion in aOperaciones)
{
comboBoxOperaciones.Items.Add(cOperacion);
}
timerForUpdate.Interval = 60000;
timerForUpdate.Enabled = true;
}
private void buttonRun_Click(object sender, EventArgs e)
{
int iOperador1, iOperador2;
string resultadoDesdeDll = null;
string cOperacionSeleccionada;
Int32.TryParse(textBoxOperador1.Text, out iOperador1);
Int32.TryParse(textBoxOperador2.Text, out iOperador2);
cOperacionSeleccionada = comboBoxOperaciones.GetItemText(comboBoxOperaciones.SelectedItem);
object[] parametersArray = new object[] { iOperador1, iOperador2 };
resultadoDesdeDll = metodosApoyo.RunDLLFunction(cOperacionSeleccionada, parametersArray);
textBoxResultado.Text = resultadoDesdeDll;
}
private void timerForUpdate_Tick(object sender, EventArgs e)
{
labelUpdateStatus.Text = "Checking updates ...";
notifyIconUpdate.Visible = true;
notifyIconUpdate.BalloonTipText = "Instalando nuevo DLL....";
notifyIconUpdate.BalloonTipTitle = "Info:";
notifyIconUpdate.ShowBalloonTip(5000);
if (File.Exists(#"C:\DLLsForCopy\OperacionesDLL.dll"))
{
File.Copy(#"C:\DLLsForCopy\OperacionesDLL.dll", #"D:\DLLs\OperacionesDLL.dll", true);
labelVersionDll.Text = metodosApoyo.RunDLLFunction("VersionOperaciones");
string cListaOperaciones = metodosApoyo.RunDLLFunction("ListaOperaciones");
string[] aOperaciones = cListaOperaciones.Split('|');
comboBoxOperaciones.Items.Clear();
foreach (string cOperacion in aOperaciones)
{
comboBoxOperaciones.Items.Add(cOperacion);
}
}
labelUpdateStatus.Text = "";
notifyIconUpdate.Visible = false;
}
}
}
Class in project, for some functions for Main application:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
namespace testDLLs
{
class metodosApoyo
{
public static string RunDLLFunction(string cMetodo, object[] aParametros = null)
{
string cRetornoGlobal = "";
Object resultado = null;
string cOperacionSeleccionada = cMetodo;
Assembly assembly = Assembly.LoadFile(#"D:\DLLs\OperacionesDLL.dll");
Type type = assembly.GetType("OperacionesDLL.Operaciones");
MethodInfo methodInfo = type.GetMethod(cOperacionSeleccionada);
ParameterInfo[] parameters = methodInfo.GetParameters();
object classInstance = Activator.CreateInstance(type, null);
object[] parametersArray = null;
if (aParametros != null)
{
parametersArray = new object[aParametros.Length];
int i = 0;
foreach (object value in aParametros)
{
parametersArray[i] = aParametros[i];
i++;
}
}
resultado = methodInfo.Invoke(methodInfo, parametersArray);
cRetornoGlobal = (string)resultado;
return cRetornoGlobal;
}
}
}
DLL source (OperacionesDLL.dll):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OperacionesDLL
{
public class Operaciones
{
public static string VersionOperaciones()
{
string retorno;
retorno = "1.0701-16";
return retorno;
}
public static string ListaOperaciones()
{
string retorno;
retorno = "Suma|Resta|Multiplicación|División";
return retorno;
}
public static string Suma(int operador1, int operador2)
{
int resultado;
string retorno;
resultado = operador1 + operador2;
retorno = resultado.ToString();
return retorno;
}
public static string Resta(int operador1, int operador2)
{
int resultado;
string retorno;
resultado = operador1 - operador2;
retorno = resultado.ToString();
return retorno;
}
public static string Multiplicación(int operador1, int operador2)
{
int resultado;
string retorno;
resultado = operador1 * operador2;
retorno = resultado.ToString();
return retorno;
}
public static string División(int operador1, int operador2)
{
int resultado;
string retorno;
resultado = operador1 / operador2;
retorno = resultado.ToString();
return retorno;
}
}
}
Thanks in advance.
You can do what you're describing by using the Managed Addin Framework (MAF) in the System.Addin namespace. I've used it to write apps that scans a folder for DLLs and dynamically loads them. You can also use it to unload and reload DLLs as they appear and disappear from the folder.
when i run a method within my WCF service i get "An unhandled exception of type 'System.StackOverflowException' occurred in developer1SVC.dll".
No infinite loops exist and no infinite recursion is occurring. Any ideas to why this may be happening? when i run the method through wcf test client. I get the results back correctly however, hooking it up to my console app and running it breaks the application. The other methods run fine. It is this one method. Just trying to get the feel for WCF services. The service breaks right after i return accounts from the "generateMultiplAccounts" method.
Much help appreciated.
Service
using developer1.Core.ServiceContracts;
using developer1.Core.Data;
using developer1.Core.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using developer1.Core.Dto.Account;
namespace developer1.Core.Service
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select Service1.svc or Service1.svc.cs at the Solution Explorer and start debugging.
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
Console.WriteLine(composite.StringValue + composite.BoolValue);
return composite;
}
public List<AccountDto> GenerateMultipleAccounts(int count)
{
List<AccountDto> accounts = new List<AccountDto>();
for (int i = 0; i < count; i++)
{
AccountDto newAccount = new AccountDto() { AccountId = Guid.NewGuid()};
accounts.Add(newAccount);
}
return accounts;
}
}
}
Console Application
using developer1.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using developer1.Core.Service;
using developer1.Core.Dto.Account;
using developer1.Core.ServiceContracts;
using AccountServiceClient = developer1.TestConsole.ServiceReference1.Service1Client;
namespace developer1.TestConsole
{
class Program
{
static void Main(string[] args)
{
try
{
AccountServiceClient AccountServiceClient = new AccountServiceClient();
Guid testGuid = Guid.NewGuid();
List<AccountDto> newAccounts = new List<AccountDto>(AccountServiceClient.GenerateMultipleAccounts(2));
Console.WriteLine(testGuid);
CompositeType testDataContract = new CompositeType() { StringValue = "test", BoolValue = true };
testDataContract = AccountServiceClient.GetDataUsingDataContract(testDataContract);
Console.WriteLine(AccountServiceClient.GetData(6));
Console.WriteLine(testDataContract.StringValue);
//foreach (var item in newAccounts)
//{
// Console.WriteLine(item.AccountId);
//}
}
catch(Exception e) {
Console.WriteLine(e);
}
Console.Read();
}
}
}
Data Contract
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Web;
namespace developer1.Core.Dto.Account
{
[DataContract]
public class AccountDto
{
[DataMember]
public Guid AccountId { get; set; }
//get { return this.AccountId; }
//set { this.AccountId = this.AccountId == Guid.Empty ? Guid.NewGuid() : value; }
[DataMember]
public Guid UserId { get; set; }
[DataMember]
public string AccountName { get; set; }
[DataMember]
public string BankName { get; set; }
//get { return this.BankName; }
//set { this.BankName = this.BankName == null ? "Unspecified" : value; }
}
}
ANSWER!!!!!!!
So I have solved this dreaded issue. You must create a WCF Service Library instead of a WCF Service Application. My god that is stupid that the application wont let you split your components outside of the interface.
I have the following code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using OpenFridge.Portable.Data.Interfaces.Entities;
using OpenFridge.Portable.Data.Parse.Entities;
using Parse;
using AutoMapper;
namespace OpenFridge.Portable.Data.Parse.Entities
{
[ParseClassName("_User")]
public class ParseUserEntity : ParseUserEntityBase, IUserEntity
{
private string _password;
[ParseFieldName("password")]
public new string Password
{
get { return _password; }
set
{
_password = value;
base.Password = value;
}
}
Lazy<IEnumerable<IBankAccountEntity>> _bankAccounts;
[ParseFieldName("bankAccounts")]
public Lazy<IEnumerable<IBankAccountEntity>> BankAccounts
{
get
{
var relation = GetRelation<ParseBankAccountEntity>("BankAccount");
if (relation == null) return null;
var result = relation.Query.FindAsync().Result;
var _bankAccounts = new Lazy<IEnumerable<IBankAccountEntity>>(() => relation.Query.FindAsync().Result);
return _bankAccounts;
}
set
{
_bankAccounts = value;
}
}
}
}
And it all seems to work quite fine, however.. once I use the .BankAccounts property I get the following exception:
Must specify a ParseObject class name when creating a ParseQuery.\r\nParameter name: className
Which I find strange since there is no way for me to define a classname with in that line of code:
(That line of code beeing:)
relation.Query.FindAsync().Result
So.. is this a bug?.. Am I doing something wrong or using it wrong?
Any ideas?
Br,
Inx