I'm thinking of this a lot like MVVM one way binding in AngularJS. I have an object (a "model") with a few properties and a few methods - something like
{
"firstName": "John",
"lastName": "Doe",
"random": () => Random.Next(),
"formatDate": (fmt, value) => new DateTime(value).ToString(fmt)
}
I'd like to define a format string which can access values from the model or call methods from it and get back the formatted string. In AngularJS I would use an expression like this
Hello {firstName} {lastName}. Today is {formatDate('d', new Date())}.
Is there a way to do something similar in C# (.NET 5)? I'm looking to do this on strings.
Here are the ideas I've come up with and the problems with them
WPF / XAML. This is a ton of overhead I don't care about. I only want to format strings.
Roslyn. This requires me to write the format expressions as valid C#. It's also a lot of work.
Formattable strings / ICustomFormatter. This doesn't have support for passing a dynamic model or for method calls.
EDIT
Here's a sample of what the calling code might look like
var formatString = person.Tenant.WelcomeMessageFormat;
var model = new
{
FirstName = person.FirstName,
LastName = person.LastName,
Random = () => Random.Next(),
FormatDate = (fmt, value) => new DateTime(value).ToString(fmt)
};
var message = ParseFormatString(formatString, model);
SendMessage(message);
// .....
public string ParseFormatString(string format, object model)
{
// what goes here?
}
Are you looking for a templating library? That seems to be what you are describing.
Here is an sample from the web http://r3c.github.io/cottle/
This is pretty much a duplicate of Dynamic string interpolation but here's the dotnet core answer.
Install nuget package System.Linq.Dynamic.Core
using System;
using System.Linq;
using System.Linq.Dynamic;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
using DynLinq = System.Linq.Dynamic;
namespace aaq
{
class Model
{
private Random _random = new Random();
public string FirstName { get; set; }
public string LastName { get; set; }
public int Random => _random.Next();
public string FormatDate(string format, DateTime value) => value.ToString(format);
};
class Program
{
static void Main(string[] args)
{
var m = new Model()
{
FirstName = "firstly",
LastName = "lastly",
};
Console.WriteLine(ReplaceMacro("a", m));
Console.WriteLine(ReplaceMacro("hello {FirstName} {LastName}", m));
Console.WriteLine(ReplaceMacro("date: {FormatDate(String.Empty, DateTime.Now)}", m));
}
static string ReplaceMacro(string value, Model m)
{
return Regex.Replace(value, #"{(?<exp>[^}]+)}", match => {
var p = Expression.Parameter(typeof(Model), "Model");
var e = DynLinq.Core.DynamicExpressionParser.ParseLambda(new[] { p }, null, match.Groups["exp"].Value);
return (e.Compile().DynamicInvoke(m) ?? "").ToString();
});
}
}
}
Console output:
a
hello firstly lastly
date: 9/20/2022 12:05:23 PM
Is it possible to simplify this logic, Is there generic way to do it.
The code finds marked attributes and parses it according to the attribute type.
Please suggest some way to optimize this code, all the data type of Product class will be string, I'm getting product input as xml directly converting serialized data to a class with decimal,int,float will not give proper error message, If there is list of item it throws error in xml we wont know which row has caused the error.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace TestSolution
{
public interface ICustomParser
{
bool Parse(string input);
}
public class DecimalParserAttribute : Attribute, ICustomParser
{
public bool Parse(string input)
{
if (input == null) return false;
decimal decimalValue;
return decimal.TryParse(input, out decimalValue);
}
}
public class intParserAttribute : Attribute, ICustomParser
{
public bool Parse(string input)
{
if (input == null) return false;
int intValue;
return int.TryParse(input, out intValue);
}
}
public class Product
{
[DecimalParser]
public string Weight { get; set; }
[intParser]
public string NoOfItems { get; set; }
[intParser]
public string GRodes { get; set; }
[intParser]
public string WRodes { get; set; }
}
class Program
{
static void Main(string[] args)
{
var sb = Validate(new Product() { NoOfItems = "1", GRodes = "4", Weight = "5", WRodes = "23" });
Console.WriteLine(sb);
sb = Validate(new Product() { NoOfItems = "1", GRodes = "4w", Weight = "5", WRodes = "23" });
Console.WriteLine(sb);
Console.ReadKey();
}
private static string Validate(Product product)
{
var sb = new StringBuilder();
foreach (var property in product.GetType().GetProperties())
{
var value = Convert.ToString(property.GetValue(product, null));
var sel = property.GetAttribute<ICustomParser>();
if (sel == null) continue;
var parserinstance = (ICustomParser)Activator.CreateInstance(sel.GetType());
if (parserinstance.Parse(value)) continue;
sb.AppendLine(string.Format("{0} Has invalid value", property.Name));
}
return sb.ToString();
}
}
public static class Extensions
{
public static T GetAttribute<T>(this PropertyInfo property)
{
return (T)property.GetCustomAttributes(false).Where(s => s is T).FirstOrDefault();
}
}
}
If you only have one type (Product), it probably isn't worth it - just write the validation code explicitly without all the fancy stuff. If, however, you have multiple types to inspect (perhaps known only at runtime):
It really depends how fast it needs to be. How often does this run? If it is periodic, then there isn't a vast amount to do - the main change would be to just cast the parser directly:
var parserInstance = (ICustomParser)sel;
(it already is the attribute type)
If it is critical path, then there is a lot you can do to beef it up, but you get into the realm of metaprogramming - which is essentially what most tools like serializers and ORMs do to reduce runtime reflection. If you're not familiar with hacking IL at runtime, I would recommend looking at a tool like "Sigil" (available on nuget) that makes it hard to get wrong (or at least: tells you what you've done wrong). Essentially, you can inspect the data structure and then emit the IL that matches what it would look like if you were doing it all in explicit code; for example, emitting IL that looks kinda like:
static readonly DecimalParserAttribute _decimal = new DecimalParserAttribute();
public static void Validate(Product product) {
var sb = new StringBuilder();
if(!_decimal.Parse(product.Weight)) {
sb.Append(...);
}
// ... etc
...,
}
Can anyone help me with this?
Required Output: "Todo job for admin"
class Program
{
static void Main(string[] args)
{
Console.WriteLine(ReplaceMacro("{job.Name} job for admin", new Job { Id = 1, Name = "Todo", Description="Nothing" }));
Console.ReadLine();
}
static string ReplaceMacro(string value, Job job)
{
return value; //Output should be "Todo job for admin"
}
}
class Job
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Two suggestions:
DataBinder.Eval
string ReplaceMacro(string value, Job job)
{
return Regex.Replace(value, #"{(?<exp>[^}]+)}", match => {
return (System.Web.UI.DataBinder.Eval(new { Job = job }, match.Groups["exp"].Value) ?? "").ToString();
});
}
Linq.Expression
Use the Dynamic Query class provided in the MSDN LINQSamples:
string ReplaceMacro(string value, Job job)
{
return Regex.Replace(value, #"{(?<exp>[^}]+)}", match => {
var p = Expression.Parameter(typeof(Job), "job");
var e = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { p }, null, match.Groups["exp"].Value);
return (e.Compile().DynamicInvoke(job) ?? "").ToString();
});
}
In my opinion, the Linq.Expression is more powerful, so if you trust the input string, you can do more interesting things, i.e.:
value = "{job.Name.ToUpper()} job for admin"
return = "TODO job for admin"
You can't use string interpolation this way. But you can still use the pre-C#6 way to do it using string.Format:
static void Main(string[] args)
{
Console.WriteLine(ReplaceMacro("{0} job for admin", new Job { Id = 1, Name = "Todo", Description = "Nothing" }));
Console.ReadLine();
}
static string ReplaceMacro(string value, Job job)
{
return string.Format(value, job.Name);
}
This generic solution Extend the answer provided by #Dan
It can be used for any typed object.
install System.Linq.Dynamic
Install-Package System.Linq.Dynamic -Version 1.0.7
string ReplaceMacro(string value, object #object)
{
return Regex.Replace(value, #"{(.+?)}",
match => {
var p = Expression.Parameter(#object.GetType(), #object.GetType().Name);
var e = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { p }, null, match.Groups[1].Value);
return (e.Compile().DynamicInvoke(#object) ?? "").ToString();
});
}
See a working demo for a Customer type
You could use RazorEngine:
using RazorEngine;
class Program
{
static void Main(string[] args)
{
Console.WriteLine(ReplaceMacro("#Model.Name job for admin", new Job { Id = 1, Name = "Todo", Description="Nothing" }));
Console.ReadLine();
}
static string ReplaceMacro(string value, Job job)
{
return Engine.Razor.RunCompile(value, "key", typeof(Job), job);
}
}
It even supports Anonymous Types and method calls:
string template = "Hello #Model.Name. Today is #Model.Date.ToString(\"MM/dd/yyyy\")";
var model = new { Name = "Matt", Date = DateTime.Now };
string result = Engine.Razor.RunCompile(template, "key", null, model);
Little late to the party! Here is the one I wrote -
using System.Reflection;
using System.Text.RegularExpressions;
public static class AmitFormat
{
//Regex to match keywords of the format {variable}
private static readonly Regex TextTemplateRegEx = new Regex(#"{(?<prop>\w+)}", RegexOptions.Compiled);
/// <summary>
/// Replaces all the items in the template string with format "{variable}" using the value from the data
/// </summary>
/// <param name="templateString">string template</param>
/// <param name="model">The data to fill into the template</param>
/// <returns></returns>
public static string FormatTemplate(this string templateString, object model)
{
if (model == null)
{
return templateString;
}
PropertyInfo[] properties = model.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
if (!properties.Any())
{
return templateString;
}
return TextTemplateRegEx.Replace(
templateString,
match =>
{
PropertyInfo property = properties.FirstOrDefault(propertyInfo =>
propertyInfo.Name.Equals(match.Groups["prop"].Value, StringComparison.OrdinalIgnoreCase));
if (property == null)
{
return string.Empty;
}
object value = property.GetValue(model, null);
return value == null ? string.Empty : value.ToString();
});
}
}
Example -
string format = "{foo} is a {bar} is a {baz} is a {qux} is a really big {fizzle}";
var data = new { foo = 123, bar = true, baz = "this is a test", qux = 123.45, fizzle = DateTime.UtcNow };
Compared with other implementations given by Phil Haack and here are the results for the above example -
AmitFormat took 0.03732 ms
Hanselformat took 0.09482 ms
OskarFormat took 0.1294 ms
JamesFormat took 0.07936 ms
HenriFormat took 0.05024 ms
HaackFormat took 0.05914 ms
Wrap the string in a function...
var f = x => $"Hi {x}";
f("Mum!");
//... Hi Mum!
You need named string format replacement. See Phil Haack's post from years ago: http://haacked.com/archive/2009/01/04/fun-with-named-formats-string-parsing-and-edge-cases.aspx/
Not exactly but with bit tweek, I have created generic interpolation which support fields / property only.
public static string Interpolate(this string template, params Expression<Func<object, string>>[] values)
{
string result = template;
values.ToList().ForEach(x =>
{
MemberExpression member = x.Body as MemberExpression;
string oldValue = $"{{{member.Member.Name}}}";
string newValue = x.Compile().Invoke(null).ToString();
result = result.Replace(oldValue, newValue);
}
);
return result;
}
Test case
string jobStr = "{Name} job for admin";
var d = new { Id = 1, Name = "Todo", Description = "Nothing" };
var result = jobStr.Interpolate(x => d.Name);
Another
string sourceString = "I wanted abc as {abc} and {dateTime} and {now}";
var abc = "abcIsABC";
var dateTime = DateTime.Now.Ticks.ToString();
var now = DateTime.Now.ToString();
string result = sourceString.Interpolate(x => abc, x => dateTime, x => now);
Starting from the accepted answer I created a generic extension method:
public static string Replace<T>(this string template, T value)
{
return Regex.Replace(template, #"{(?<exp>[^}]+)}", match => {
var p = Expression.Parameter(typeof(T), typeof(T).Name);
var e = System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(new[] { p }, null, match.Groups["exp"].Value);
return (e.Compile().DynamicInvoke(value) ?? "").ToString();
});
}
Answer from #ThePerplexedOne is better, but if you really need to avoid string interpolation, so
static string ReplaceMacro(string value, Job job)
{
return value?.Replace("{job.Name}", job.Name); //Output should be "Todo job for admin"
}
You should change your function to:
static string ReplaceMacro(Job obj, Func<dynamic, string> function)
{
return function(obj);
}
And call it:
Console.WriteLine(
ReplaceMacro(
new Job { Id = 1, Name = "Todo", Description = "Nothing" },
x => $"{x.Name} job for admin"));
If you really need this, you can do it using Roslyn, create string – class implementation like
var stringToInterpolate = "$#\"{{job.Name}} job for admin\"";
var sourceCode = $#"
using System;
class RuntimeInterpolation(Job job)
{{
public static string Interpolate() =>
{stringToInterpolate};
}}";
then make an assembly
var assembly = CompileSourceRoslyn(sourceCode);
var type = assembly.GetType("RuntimeInterpolation");
var instance = Activator.CreateInstance(type);
var result = (string) type.InvokeMember("Interpolate",
BindingFlags.Default | BindingFlags.InvokeMethod, null, instance, new object[] {new Job { Id = 1, Name = "Todo", Description="Nothing" }});
Console.WriteLine(result);
you'll get this code by runtime and you'll get your result (also you'll need to attach link to your job class to that assembly)
using System;
class RuntimeInterpolation(Job job)
{
public static string Interpolate() =>
$#"{job.Name} job for admin";
}
You can read about how to implement CompileSourceRoslyn here Roslyn - compiling simple class: "The type or namespace name 'string' could not be found..."
Wondering no one has mentioned mustache-sharp. Downloadable via Nuget.
string templateFromSomewhere = "url: {{Url}}, Name:{{Name}}";
FormatCompiler compiler = new FormatCompiler();
Generator generator = compiler.Compile(templateFromSomewhere);
string result = generator.Render(new
{
Url="https://google.com",
Name = "Bob",
});//"url: https://google.com, Name:Bob"
More examples could be found here, at the unit testing file.
The implementation I'd come up with very similar to giganoide's allowing callers to substitute the name used in the template for the data to interpolate from. This can accommodate things like feeding it anonymous types. It will used the provided interpolateDataAs name if provided, otherwise if it isn't an anonymous type it will default to the type name, otherwise it expects "data". (or specifically the name of the property) It's written as an injectable dependency but should still work as an extension method.
public interface ITemplateInterpolator
{
/// <summary>
/// Attempt to interpolate the provided template string using
/// the data provided.
/// </summary>
/// <remarks>
/// Templates may want to use a meaninful interpolation name
/// like "enquiry.FieldName" or "employee.FieldName" rather than
/// "data.FieldName". Use the interpolateDataAs to pass "enquiry"
/// for example to substitute the default "data" prefix.
/// </remarks>
string? Interpolate<TData>(string template, TData data, string? interpolateDataAs = null) where TData : class;
}
public class TemplateInterpolator : ITemplateInterpolator
{
/// <summary>
/// <see cref="ITemplateInterpolator.Interpolate(string, dynamic, string)"/>
/// </summary>
string? ITemplateInterpolator.Interpolate<TData>(string template, TData data, string? interpolateDataAs)
{
if (string.IsNullOrEmpty(template))
return template;
if (string.IsNullOrEmpty(interpolateDataAs))
{
interpolateDataAs = !typeof(TData).IsAnonymousType() ? typeof(TData).Name : nameof(data);
}
var parsed = Regex.Replace(template, #"{(?<exp>[^}]+)}", match =>
{
var param = Expression.Parameter(typeof(TData), interpolateDataAs);
var e = System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(new[] { param }, null, match.Groups["exp"].Value);
return (e.Compile().DynamicInvoke(data) ?? string.Empty).ToString();
});
return parsed;
}
For detecting the anonymous type:
public static bool IsAnonymousType(this Type type)
{
if (type.IsGenericType)
{
var definition = type.GetGenericTypeDefinition();
if (definition.IsClass && definition.IsSealed && definition.Attributes.HasFlag(TypeAttributes.NotPublic))
{
var attributes = definition.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false);
return (attributes != null && attributes.Length > 0);
}
}
return false;
}
Test Suite:
[TestFixture]
public class WhenInterpolatingATemplateString
{
[TestCase("")]
[TestCase(null)]
public void ThenEmptyValueReturedWhenNoTemplateProvided(string? template)
{
ITemplateInterpolator testInterpolator = new TemplateInterpolator();
var testData = new TestData { Id = 14, Name = "Test" };
var result = testInterpolator.Interpolate(template!, testData);
Assert.That(result, Is.EqualTo(template));
}
[Test]
public void ThenTheTypeNameIsUsedForTheDataReferenceForDefinedClasses()
{
ITemplateInterpolator testInterpolator = new TemplateInterpolator();
var testData = new TestData { Id = 14, Name = "Test" };
string template = "This is a record named \"{TestData.Name}\" with an Id of {testdata.Id}."; // case insensitive.
string expected = "This is a record named \"Test\" with an Id of 14.";
var result = testInterpolator.Interpolate(template, testData);
Assert.That(result, Is.EqualTo(expected));
}
[Test]
public void ThenTheDefaultNameIsUsedForTheDataReferenceForAnonymous()
{
ITemplateInterpolator testInterpolator = new TemplateInterpolator();
var testData = new { Id = 14, Name = "Test" };
string template = "This is a record named \"{data.Name}\" with an Id of {data.Id}.";
string expected = "This is a record named \"Test\" with an Id of 14.";
var result = testInterpolator.Interpolate(template, testData);
Assert.That(result, Is.EqualTo(expected));
}
[Test]
public void ThenTheProvidedDataReferenceNameOverridesTheTypeName()
{
ITemplateInterpolator testInterpolator = new TemplateInterpolator();
var testData = new TestData { Id = 14, Name = "Test" };
string template = "This is a record named \"{otherData.Name}\" with an Id of {otherData.Id}.";
string expected = "This is a record named \"Test\" with an Id of 14.";
var result = testInterpolator.Interpolate(template, testData, "otherData");
Assert.That(result, Is.EqualTo(expected));
}
[Test]
public void ThenExceptionIsThrownWhenTemplateReferencesUnknownDataValues()
{
ITemplateInterpolator testInterpolator = new TemplateInterpolator();
var testData = new TestData { Id = 14, Name = "Test" };
string template = "This is a record named \"{testData.Name}\" with an Id of {testData.Id}. {testData.ExtraDetails}";
Assert.Throws<ParseException>(() => { var result = testInterpolator.Interpolate(template, testData, "testData"); });
}
[Test]
public void ThenDataFormattingExpressionsAreApplied()
{
ITemplateInterpolator testInterpolator = new TemplateInterpolator();
var testData = new { Id = 14, Name = "Test", IsActive = true, EffectiveDate = DateTime.Today };
string template = "The active state is {data.IsActive?\"Yes\":\"No\"}, Effective {data.EffectiveDate.ToString(\"yyyy-MM-dd\")}";
string expected = "The active state is Yes, Effective " + DateTime.Today.ToString("yyyy-MM-dd");
var result = testInterpolator.Interpolate(template, testData);
Assert.That(result, Is.EqualTo(expected));
}
private class TestData
{
public int Id { get; set; }
public string Name { get; set; }
}
}
I really don't understand the point of your ReplaceMacro method...
But here's how it should work:
class Program
{
static void Main(string[] args)
{
var job = new Job { Id = 1, Name = "Todo", Description = "Nothing" };
Console.WriteLine($"{job.Name} job for admin");
Console.ReadLine();
}
}
But if you really want the dynamic feel to it, your ReplaceMacro method should just take one parameter, which is the job:
static string ReplaceMacro(Job job)
{
return $"{job.Name} job for admin.";
}
And use it like:
var job = new Job { Id = 1, Name = "Todo", Description = "Nothing" };
Console.WriteLine(ReplaceMacro(job));
Or something to that effect.
I often want to parse a string into various bits and have a readable way to return them.
I like this approach, but it involves creating a specific class
long orderID = Utils.UnTradeIdent(tradeIdent).OrderID;
In Utils.cs:
public class TradeIdentData
{
public string AccountIdent;
public long OrderID;
public string SubID;
}
public static TradeIdentData UnTradeIdent(string tradeIdent)
{
TradeIdentData tradeIdentData = new TradeIdentData();
var parts = tradeIdent.Split('!');
tradeIdentData.AccountIdent = parts[0];
if (parts[1].Contains("."))
{
var bits = parts[1].Split('.');
tradeIdentData.OrderID = long.Parse(bits[1]);
tradeIdentData.SubID = bits[1];
}
else
{
tradeIdentData.OrderID = long.Parse(parts[1]);
tradeIdentData.SubID = "";
}
return tradeIdentData;
}
A separate class with well-named properties (which you are already using) is currently the most readable way of doing this.
In C# 7 you will be able to use tuples for return values, like so:
public static (string AccountIdent, string OrderID, string SubID) UnTradeIdent(string tradeIdent)
{
string accountIdent, orderID, subID ;
... Code to initialise accountIdent, orderID and subID appropriately ...
// Now return the data as a tuple:
return (accountIdent, orderID, subID);
}
You can consume this as follows:
long orderID = Utils.UnTradeIdent(tradeIdent).OrderID;
Or if you want all the values:
var result = Utils.UnTradeIdent(tradeIdent);
// Use result.OrderId, result.SubID or result.AccountIdent
This is not going to be available until some time next year, though.
Also, even though this new tuple support makes it more convenient to WRITE the code, it doesn't let you document it using XML comments as well. Spending the time to write a simple and well-documented class will still often be better than using the new C# 7 tuple support.
See here for more details.
You can also use the out keyword to pass arguments by reference, see MSDN article out (C# Reference):
public static void UnTradeIdent(string tradeIdent, out string AccountIdent, out long OrderID, out string SubID)
{
var parts = tradeIdent.Split('!');
AccountIdent = parts[0];
if (parts[1].Contains("."))
{
var bits = parts[1].Split('.');
OrderID = long.Parse(bits[1]);
SubID = bits[1];
}
else
{
OrderID = long.Parse(parts[1]);
SubID = "";
}
}
UPDATED with suggestion from comments:
public static bool UnTradeIdent(string tradeIdent, out string AccountIdent, out long OrderID, out string SubID)
{
bool result = false;
AccountIdent = "";
OrderID = 0;
SubID = "";
try
{
var parts = tradeIdent.Split('!');
AccountIdent = parts[0];
if (parts[1].Contains("."))
{
var bits = parts[1].Split('.');
OrderID = long.Parse(bits[1]);
SubID = bits[1];
}
else
{
OrderID = long.Parse(parts[1]);
SubID = "";
}
}
catch(ArgumentNullException ane)
{
// Handle parsing exception
}
catch (FormatException fe)
{
// Handle parsing exception
}
catch (OverflowException oe)
{
// Handle parsing exception
}
return result;
}
Its pretty simple to do just by changing the return type to dynamic and using an anonymous class
public static dynamic UnTradeIdent(string tradeIdent)
{
var value1 = //parselogic
var value2 = //parselogic
return new { Identity = value1, Item2 = value2};
}
I would consider making additional static methods. Your current implementation is cleaner when you require all of the returned properties, but something like below might be appropriate when you only need one of them.
public static string TradeIdentToAccountIdent(string tradeIdent)
{
var parts = tradeIdent.Split('!');
return parts[0];
}
public static long TradeIdentToOrderID(string tradeIdent)
{
var parts = tradeIdent.Split('!');
if (parts[1].Contains("."))
{
var bits = parts[1].Split('.');
return long.Parse(bits[1]); // Taken from your example, should probably be bits[0]?
}
else
return long.Parse(parts[1]);
}
// My own take on it this time, you could obviously use your logic as well.
public static string TradeIdentToSubID(string tradeIdent)
{
var order = tradeIdent.Split('!')[1];
if (order.Contains("."))
return order.Split('.')[1];
else
return String.Empty;
}
I am currently working with displaying a list of items. I have created a method GetNextItem that returns obj1. When I am calling the method from the buttonClick I get this following error:
Cannot implicitly convert type 'TreeFarm.Form1.fruit_trees' to 'string'.
Not sure why is doing such thing.
public items_list GetNextItem()
{
items_list obj1 = this.current_item;
if (obj1 != null)
{
current_item = current_item.next_item;
}
return obj1;
}
ListForItems mainlist = new ListForItems();
private void ShowNextItem_Click(object sender, EventArgs e)
{
labelSpecificItem.Text = mainlist.GetNextItem();
}
You're trying to convert a value of type items_list in to a string (.Text is of String type). So, if this is one of your objects you can create an implicit cast operator or maybe try using .ToString() or explicitly casting it to a string using (String)mainlist.GetNextItem().
if you desire this kind of assignment and items_list is one of your objects, I would suggest the following addition to that class:
public static implicit operator String(items_list itemslist)
{
return /* however you want to portray itemslist as a string */;
}
Otherwise you're going to have to rely on ToString() getting it right.
As other answers have mentioned, you cannot cast your items_list object to a string. If there is a component of items_list that you want to appear in your label, then assign that instead of the whole object:
labelSpecificItem.Text = mainlist.GetNextItem().textYouWantToSee;
Your items need to override the ToString() method, and then use that to convert them into strings.
Follow this pattern:
public class FruitTree
{
public string Name { get; set; }
// your code
public override string ToString()
{
return string.Format("A {0} tree.", Name);
}
}
// later in the click handler
{
labelSpecificItem.Text = tree_item.ToString();
}
I had this problem myself, but that's because I forgot how it was done.
This was my code before:
public static string MakeRequest(string GetCountry, string GetTime, string Server, string Database)
{
var filter = Builders<RequestAccess>.Filter;
var getCountryfilter = filter.Eq(x => x.GetCountry, GetCountry);
var getTimefilter = filter.Eq(x => x.GetTime, GetTime);
var databasefilter = filter.Eq(x => x.Database, Database);
var serverfilter = filter.Eq(x => x.Servers, Server);
var makeRequest = RequestCollection.Find(filter.Or(getCountryfilter, getTimefilter, databasefilter, serverfilter)).ToList();
return makeRequest;
}
But the code below is the correct one :)
public static List<RequestAccess> MakeRequest(string GetCountry, string GetTime, string Server, string Database)
{
var filter = Builders<RequestAccess>.Filter;
var getCountryfilter = filter.Eq(x => x.GetCountry, GetCountry);
var getTimefilter = filter.Eq(x => x.GetTime, GetTime);
var databasefilter = filter.Eq(x => x.Database, Database);
var serverfilter = filter.Eq(x => x.Servers, Server);
var makeRequest = RequestCollection.Find(filter.Or(getCountryfilter, getTimefilter, databasefilter, serverfilter)).ToList();
return makeRequest;
}
So that means if you're trying to make a list of something then dont use "string" in public static ... :)