Trying to build a formatting delegate/function. It's mainly for printing exercise results.
I am trying to access the result of a argument but I think my understanding of delegates is still kind of bad. The method is invokable in the block itself but I would like the result, currently it prints the result definition.
System.Func2[ConsoleApp1.LoanQueries,System.Collections.Generic.IEnumerable
1[System.Decimal]]
Below is the code that will create to result to parse, the parsing method and a code snippet that I based my code on.
My questions are:
Create data to format
// Method bodied expression
public IEnumerable<decimal> LoanQueryBodied =>
from amount in LoanAmounts
where amount % 2 == 0
orderby amount ascending
select amount;
// Query expression:
public IEnumerable<decimal> LoanQueryExpression () =>
LoanAmounts
.Where(a => a % 2 == 0)
.OrderBy(r => r);
Method for data and final formatting
public static void FormatLoans<TObject>(
Func<TObject> instance,
Func<TObject, IEnumerable<decimal>> function)
{
// This is the function object but should be IEnumerable<decimal> result passed down.
// Just like TObject is passed , but how?
Console.WriteLine(string.Join(" - ",function));
}
Use method
LoanQueries.FormatLoans<LoanQueries>(() =>
new LoanQueries()
, inst => inst.LoanQueryBodied);
LoanQueries.FormatLoans<LoanQueries>(() =>
new LoanQueries()
, inst => inst.LoanQueryExpression());
Code that I based it loosely on
public static class Disposable
{
public static TResult Using<TDisposable, TResult>(
Func<TDisposable> factory,
Func<TDisposable, TResult> map)
where TDisposable : IDisposable
{
using (var disposable = factory())
{
return map(disposable);
}
}
}
Example invoked
var time= Disposable
.Using(
() => new WebClient(),
client => XDocument.Parse(client.DownloadString("http://time.gov/actualtime.cgi")))
.Root
.Attribute("time")
.Value;
I would like to chain my method like this but if this is not possible or bad practice I would also like to know.
You need to call function
and instance
using ()
:
Console.WriteLine(string.Join(" - ",function(instance())));
And apparently you want to return the string, rather than printing it, to allow chaining, so:
public static string FormatLoans<TObject>(
Func<TObject> instance,
Func<TObject, IEnumerable<decimal>> function) =>
string.Join(" - ",function(instance()));
However, I think you are really over-complicating/over-generalising this. Your method is not nearly as general as the Disposable.Using
method you showed. Your method could just be declared like this:
public static string FormatLoans(IEnumerable<decimal> loans) =>
string.Join(" - ", loans);
Callers:
LoanQueries.FormatLoans(new LoanQueries().LoanQueryBodied)
LoanQueries.FormatLoans(new LoanQueries().LoanQueryExpression)
Disposable.Using
uses delegates because it is trying to recreate the using
statement. The second argument must be evaluated inside the using
statement, so that any exceptions thrown lead to the disposal of the IDisposable
, which is why it has to be wrapped up in a delegate. If not, the second argument would be evaluated before the Using
method runs, and that misses the whole point.
However, your method does not have special requirements like that, so you don't need delegates.