Difference between SendAsync and SendCoreAsync methods in SignalR Core? - asp.net-core-signalr

When updating to the latest version of ASP Net Core and SignalR core, I noticed there are two "send" methods available when sending methods to a client (what used to be InvokeAsync).
After looking at the code comments, both methods are identical in comments, both inherit from IClientProxy, and both accept a string method, object args and then a cancellation token.
What are the differences in these methods? If any? and which should be used when?

Quoting #anurse from GitHub:
Long story short:
The Core methods should be ignored unless you really know what you're doing.
Short story long:
We started with SendAsync, which takes an array of arguments to send:
public void SendAsync(string method, object[] args);
Clients.All.SendAsync("Method", new object[] { arg1, arg2, arg3 });
Obviously it's a pain to have to create an array every time. The easy
fix for that would be to use params:
public void SendAsync(string method, params object[] args);
Clients.All.SendAsync("Method", arg1, arg2, arg3);
However, that falls apart when you actually want to send an array as a
single argument
public void SendAsync(string method, params object[] args);
var arg1 = new object[] { a, b, c };
Clients.All.SendAsync("Method", arg1);
// C# 'params' expands this into the below
Clients.All.SendAsync("Method", a, b, c);
So instead of sending a single argument that is an array a, b, c,
we've sent each of those as separate arguments. This was confusing
users.
So we removed the params from it and instead we generate a whole bunch
of extension methods that support multiple arguments:
public void SendAsync(string method, object[] args);
public void SendAsync(string method, object arg1) => SendAsync(method, new object[] { arg1 });
public void SendAsync(string method, object arg1, object arg2) => SendAsync(method, new object[] { arg1, arg2 });
// ... etc ...
But there's still ambiguity when you have code like this:
public void SendAsync(string method, object[] args);
public void SendAsync(string method, object arg1) => SendAsync(method, new object[] { arg1 });
var arg = new object[] { a, b, c }
Clients.All.SendAsync("method", arg);
Again, the overload that takes an object[] will be chosen (see this
illustration on SharpLab).
So, we renamed the one that takes an array to SendCoreAsync:
public void SendCoreAsync(string method, object[] args);
public void SendAsync(string method, object arg1) => SendCoreAsync(method, new object[] { arg1 });
var arg = new object[] { a, b, c }
// No ambiguity here!
Clients.All.SendAsync("method", arg);

Related

Mapstruct : Use of context in source argument of #Mapping

When using multiple arguments in a #Mapper, it seems that the #Context arguments is unreachable
public interface MyMapper {
#Mapping(target="target1", source="arg1.arg") //works
#Mapping(target="target2", source="arg2") //works
#Mapping(target="target3", source="arg2.arg") //works
#Mapping(target="target2", source="context.arg") //NOT WORKING
public MyTarget convert(Object arg1, Object arg2, #Context Object context);
}
I am trying to use and expression="" to work around it, but I can't get it to work.
Any suggestions?
I can see I am not the only one to ever wish this.
https://github.com/mapstruct/mapstruct/issues/1280
Thanks
I ran into the same scenario as I needed a #Context param to be able to pass to a nested mapping function, but also wanted to use it as a source in a #Mapping. I was able to achieve this using expression as follows:
public interface MyMapper {
#Mapping(target="target1", source="arg1")
#Mapping(target="target2", source="arg2")
#Mapping(target="target3", expression="java( contextArg )")
public MyTarget convert(Object arg1, Object arg2, #Context Object contextArg);
}
To answer your second question:
public interface MyMapper {
#Mapping(target="target1", source="arg1.arg")
#Mapping(target="target2", ignore = true ) // leave to after mapping
MyTarget convert(Object arg1, #Context Object context);
#AfterMapping
default convert(Object arg1, #MappingTarget MyTarget target, #Context context) {
target.setTarget2( convert ( context ) );
}
// if you have multipe mappings, you could address them here
#Mapping(target="target2", source="context.arg")
MyInnerTarget convert(Object arg1, Object context);
}
By definition a #Context annotated object is not a source. It is context So you can't use it as source in the #Mapping(target="target2", source="context.arg")
Here is a related github issue with official answer: github issue
Not really clean, but it seems having the same object as source and context allows to use it both ways.
#Mapping(target="target1", source="arg1.arg")
#Mapping(target="target2", source="arg2")
#Mapping(target="target3", source="arg2.arg")
#Mapping(target="target4", source="contextAsSource.arg")
public MyTarget convert(Object arg1, Object arg2, Object contextAsSource, #Context Object context);
Here contextAsSource and context are the same.

how can we apply aspect oriented programming on a particular line of java class ?

How can we apply aop on the last line of main method ?
Below is a test class for call by value in java. I have been asked in one interview to apply Aspect oriented programming on last line of the class. Is it possible to apply AOP on a particular line of any java class, if yes then please give some example code.
public class TestCallByValue {
public static void main(String[] args) {
Student st = new Student("Sanjeev", 1);
changeName(st);
System.out.println(st.getName());//apply aop on this line to stop printing sysout
}
public static void changeName(Student st) {
st = new Student("Rajeev", 2);
st.setName("Amit");
}
}
class Student {
String name;
Integer id;
public Student(String name, Integer id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
What can be applied on a particular line of java code is called a joinpoint
This link lists the possible joinpoints you can set in your code, with aspectj. As you can see, only constructor call, method call, field initialization, etc. can be defined as joinpoints
The only way is to apply a pointcut on System.out#println. You could as well encapsulate System.out.println(st.getName()); in a dedicated method
AspectJ doesn't operate on source code, it operates on the semantic structure of Java programs. As such, it doesn't have a concept of "lines". The interviewer meant that you should prevent a particular method call from happening, and told you where that method call is, in this particular case it's the last statement of the main method.
This statement is located in TestCallByValue.main() method and invokes println() on System.out, which is a PrintStream. While we cannot indicate to AspectJ that we want to prevent only the "last" statement from executing, we can narrow this down to
method calls to the println method of the PrintStream class, accepting a String and returning void, within the code contained in the TestCallByValue.main() method that accepts an array of Strings and returns void
To prevent the method call from happening, you will need an around advice which doesn't call proceed(). We can also check whether the target of the method call is actually System.out, so we prevent only System.out.println(String), not println(String) calls on other instances of PrintStream.
The above can be achieved with the following aspect:
aspect DummyAspect {
pointcut printlnStatementInMain(): withincode(void TestCallByValue.main(String[]))
&& call(void java.io.PrintStream.println(String));
void around(): printlnStatementInMain() {
if (thisJoinPoint.getTarget() != System.out) {
proceed();
}
}
}

Differences between Assert.True and Assert.IsTrue in NUnit?

Is there any differences between those two?
No difference. Assert.True() and others (without Is) were added since v2.5.
From documentation for the version 2.5: (nunit v2.5)
Two forms are provided for the True, False, Null and NotNull
conditions. The "Is" forms are compatible with earlier versions of the
NUnit framework, while those without "Is" are provided for
compatibility with NUnitLite
BTW, Disassembled nunit.framework.dll (using ILSPY)
public static void IsTrue(bool condition)
{
Assert.That(condition, Is.True, null, null);
}
public static void True(bool condition)
{
Assert.That(condition, Is.True, null, null);
}
There does not seem to be any implementational difference. Looking at the source code for the most recent version here, the True, IsTrue and That are all implemented in the same way when the argument lists are the same:
public static void True(bool condition, string message, params object[] args)
{
Assert.That(condition, Is.True, message, args);
}
...
public static void IsTrue(bool condition, string message, params object[] args)
{
Assert.That(condition, Is.True, message, args);
}
...
static public void That(bool condition, string message, params object[] args)
{
Assert.That(condition, Is.True, message, args);
}
The overloaded methods are implemented analogously.

Forcing the use of a specific overload of a method in C#

I have an overloaded generic method used to obtain the value of a property of an object of type PageData. The properties collection is implemented as a Dictionary<string, object>. The method is used to avoid the tedium of checking if the property is not null and has a value.
A common pattern is to bind a collection of PageData to a repeater. Then within the repeater each PageData is the Container.DataItem which is of type object.
I wrote the original extension method against PageData:
public static T GetPropertyValue<T>(this PageData page, string propertyName);
But when data binding, you have to cast the Container.DataItem to PageData:
<%# ((PageData)Container.DataItem).GetPropertyValue("SomeProperty") %>
I got a little itch and wondered if I couldn't overload the method to extend object, place this method in a separate namespace (so as not to pollute everything that inherits object) and only use this namespace in my aspx/ascx files where I know I've databound a collection of PageData. With this, I can then avoid the messy cast in my aspx/ascx e.g.
// The new overload
public static T GetPropertyValue<T>(this object page, string propertyName);
// and the new usage
<%# Container.DataItem.GetPropertyValue("SomeProperty") %>
Inside the object version of GetPropertyValue, I cast the page parameter to PageData
public static T GetPropertyValue<T>(this object page, string propertyName)
{
PageData data = page as PageData;
if (data != null)
{
return data.GetPropertyValue<T>(propertyName);
}
else
{
return default(T);
}
}
and then forward the call onto, what I would expect to be PageData version of GetPropertyValue, however, I'm getting a StackOverflowException as it's just re-calling the object version.
How can I get the compiler to realise that the PageData overload is a better match than the object overload?
The extension method syntax is just syntactic sugar to call static methods on objects. Just call it like you would any other regular static method (casting arguments if necessary).
i.e.,
public static T GetPropertyValue<T>(this object page, string propertyName)
{
PageData data = page as PageData;
if (data != null)
{
//will call the GetPropertyValue<T>(PageData,string) overload
return GetPropertyValue<T>(data, propertyName);
}
else
{
return default(T);
}
}
[edit]
In light of your comment, I wrote a test program to see this behavior. It looks like it does go with the most local method.
using System;
using Test.Nested;
namespace Test
{
namespace Nested
{
public static class Helper
{
public static void Method(this int num)
{
Console.WriteLine("Called method : Test.Nested.Helper.Method(int)");
}
}
}
static class Helper
{
public static void Method(this object obj)
{
Console.WriteLine("Called method : Test.Helper.Method(object)");
}
}
class Program
{
static void Main(string[] args)
{
int x = 0;
x.Method(); //calls the object overload
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
Console.WriteLine();
}
}
}
To make sure the nesting is not affecting anything, tried this also removing the object overload:
using System;
using Test.Nested;
namespace Test
{
namespace Nested
{
public static class Helper
{
public static void Method(this int num)
{
Console.WriteLine("Called method : Test.Nested.Helper.Method(int)");
}
}
}
static class Helper
{
public static void Method(this string str)
{
Console.WriteLine("Called method : Test.Helper.Method(string)");
}
}
class Program
{
static void Main(string[] args)
{
int x = 0;
x.Method(); //calls the int overload
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
Console.WriteLine();
}
}
}
Sure enough, the int overload is called.
So I think it's just that, when using the extension method syntax, the compiler looks within the current namespace first for appropriate methods (the "most local"), then other visible namespaces.
It should already be working fine. I've included a short but complete example below. I suggest you double-check your method signatures and calls, and if you're still having problems, try to come up with a similar short-but-complete program to edit into your question. I suspect you'll find the answer while coming up with the program, but at least if you don't, we should be able to reproduce it and fix it.
using System;
static class Extensions
{
public static void Foo<T>(this string x)
{
Console.WriteLine("Foo<{0}>(string)", typeof(T).Name);
}
public static void Foo<T>(this object x)
{
Console.WriteLine("Foo<{0}>(object)", typeof(T).Name);
string y = (string) x;
y.Foo<T>();
}
}
class Test
{
static void Main()
{
object s = "test";
s.Foo<int>();
}
}

Using structuremap with log4net wrapper

I have the following interface:
public interface ILogger
{
void Debug(string message, params object[] values);
void Info(string message, params object[] values);
void Warn(string message, params object[] values);
void Error(string message, params object[] values);
void Fatal(string message, params object[] values);
}
and the following implementation:
public class Log4netLogger : ILogger
{
private ILog _log;
public Log4netLogger(Type type)
{
_log = LogManager.GetLogger(type);
}
public void Debug(string message, params object[] values)
{
_log.DebugFormat(message, values);
}
// other logging methods here...
}
My idea was to use structuremap to instantiate the Log4netLogger class with using the Type of the class that did the logging. However, I can't for the life of me figure out how to pass the type of the calling class to structuremap so that it can be passed to the constructor of the logging implementation. Any advice on how to do that (or a better way) would be most appreciated.
We use a similar ILogger wrapper around log4net and typically use constructor injection. We use an interceptor as a factory method responsible for creating the Logger. Here is our typical registry for logging setup.
public class CommonsRegistry : Registry
{
public CommonsRegistry()
{
For<ILogger>()
.AlwaysUnique()
.TheDefault.Is.ConstructedBy(s =>
{
if (s.ParentType == null)
return new Log4NetLogger(s.BuildStack.Current.ConcreteType);
return new Log4NetLogger(s.ParentType);
});
var applicationPath = Path.GetDirectoryName(Assembly.GetAssembly(GetType()).Location);
var configFile = new FileInfo(Path.Combine(applicationPath, "log4net.config"));
XmlConfigurator.ConfigureAndWatch(configFile);
}
}
The parent type null check is necessary when there are dependencies on concrete types.
The rest is optional log4net setup stuff.
One thing I do like about this setup is the ability to use a null loggers for unit testing.
If the type parameter is context-specific, I don't think this is going to work as shown. If you need to pass something context specific in the constructor, you are likely going to have to create a factory interface and implementation that returns an instance of the ILogger:
public interface ILoggerFactory
{
ILogger Create(Type type);
}
public class LoggerFactory : ILoggerFactory
{
public ILogger Create(Type type)
{
return new Log4netLogger(type);
}
}
It might be possible to bootstrap StructureMap to supply the instance you want based on the type, but that assumes a limited number of types that you know in advance.
I really need to get out of the habit of answering my own question, but for those who run across it, here's the answer.
return ObjectFactory.With(type).GetInstance<T>();
I actually have a wrapper to structuremap (to avoid exposing the structuremap dependency to my app) that looks like the following:
public static class ServiceManager
{
public static T Get<T>()
{
return ObjectFactory.GetInstance<T>();
}
public static T Get<T>(Type type)
{
return ObjectFactory.With(type).GetInstance<T>();
}
}
Any time in the code I need a logger, I call the following:
ServiceManager.Get<ILogger>(GetType()).Info("Logging page view...");