Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
First and formost, I am not a native english speaker, sorry for any communication errors this question might emit. Also, couldn't really understand some of your guidelines for asking a question, so followed what I understood of it. As a consequence, please tell me if I violate any custom.
background
I have been making an app that trys to implement something like xaml hot reload for code. As I can't directly make it with compiled languages like c#, I decided I will rely on a third-party scripting language, thinking I could write a bit of my app logic in it, then deploy it faster to the device because I would only need to press a button to send the code across. So, one can think of it like the expo client in the react-native world.
I decided to use lua as the scripting language, not only because it's very simple to write code in, but also because it has a nice binding for .net, I'm talking about Nlua, of course. And, as ironpython3 is not ready for production yet, what choices do I have honestly?
the problem I am facing
So, as I have to bind some xamarin.essentials stuff to make it easier for me to write the lua side of the app, I have to interface with some objects that have, among many other things, static methods. I thought it would be very intuitive and straight-forward to use static methods in Nlua, though it seemns I was mistaken so far.
how to reproduce the issue
So, in visual studio, create a xamarin.forms project, name it however you like, it doesn't matter.
Next, add the Nlua nuget package to all your projects. It needs to be integrated in all of them because it, like some xamarin.forms plugins, relies on native libraries to work, so they need to be included in the proper places for the OS to find them. This is automatically done by the package when installed in a supported project type, so do that.
Add the Nlua namespace to the top of the codebehind of your MainPage content page, like this:
using NLua;
For easy use going forward, add a class level property to the MainPage class, like this:
Lua LuaState{get; set;}
Now, initialise it in the page constructor, for simplicity's sake:
LuaState = new Lua();
In the xaml of the page, add an edit field in which to input the text and a button to be able to run it:
<StackLayout>
<Editor
x:Name="edCode"
Placeholder="type your code here"
/>
<Button
x:Name="btnStartCode"
Text="compile"
HorizontalOptions="End"
VerticalOptions="EndAndExpand"
Clicked="btnStartCode_Clicked"
/>
</StackLayout>
In the button clicked handler, add code to load the things in the edit box, then make nlua execute it, something like this:
async void btnStartCode_Clicked(object sender, EventArgs e)
{
try
{
LuaState.DoString(edCode.Text);
}
catch (Exception exc)
{
await DisplayAlert("error", $"A fatal error was incountered while running your code\nException details:\n\tException type: {exc.GetType().ToString()}\n\terror message from interpreter:{exc.Message}.", "OK");
}
}
Now, add a new class, call it however you want, I called mine tts. Delete everything inside the file vs generated, then add the following content in it:
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Essentials;
namespace autoaccess.scriptables
{
public class tts
{
public async void speak(params object[] messages)
{
foreach(var message in messages)
{
if (message == null)
{
await TextToSpeech.SpeakAsync("null value");
return;
}
await TextToSpeech.SpeakAsync(message.ToString());
}
}
}
}
Back in the main content class, either in the constructor or in a dedicated method called from the constructor, register the lua type, like this:
LuaState["text_to_speech"=typeof(TextToSpeech);
expected behaviour
It should speak the params given to the function if using . notation, e.g tts.speak("hello world")
actual behaviour
When a call with . notation is executed, the lua interpreter throws the following error:
[string "chunk"]:1: attempt to call a nil value (field 'speak').
what I tryed so far
First, I tried to get the type of the static object with the typeof keyword, then registering it directly as a lua accessible value, like I have shown above. This threw an error, as you could see.
If, for example, I try to invoke the type like a function to get a new object like shown in the documentation, it fails again.
If I use the State.UseClrPackage(); method, then importing the stuff manually, it doesn't work either, can't access any of the methods or variables, lua says they're all "nill".
Note: Upon closer inspection, I see the variable lua sees is actually the real clr type, since the str function of lua shows the full type qualifier, as present in .net. However, the type function returns userdata.
Instead of making the entire type be visible to lua as it is, I tried to make a lua table with the name, then add key-value pairs where the key is the method name, and the value is a static object's method, as returned by typeof(thing).GetMethod(MethodName) cast to the LuaFunction type.
This worked to a certain point, though it quickly grue too complicated and overwhelmingfor me, so I stopped using that approach, as my codebase grue very intangled.
Another thing I tryed is to make proxi objects for static ones in which nothing is actually static, even though the methods return void and are acting on static properties.
That, again, kind of worked, but I then necessarely had to use the object:thing, when the norm for static methods is object.thing. If I tryed to use the object.thing notation, I got a pretty long error, though I'm sure it's content is not relevant to the problem at hand, so not going to include it here.
conclusion
So, officially, I tryed everything I could, even did a search on here to see if I would be able to find anything to enlighten me, though no luck, unfortunately. Now, what do you recommend I use? Is there something I overlooked somewhere?
Placed here for the sake of it, originally I wrote this question on Blazors subreddit as it was an odd question.
Problem:
I need to call StateHasChanged to let Blazor know I've changed the input fields with JS (A library I have to implement, I'm stuck with this regardless so I need to find this solution.)
Description and solutions I've tried:
I've checked an issue created 2 years back, but it does not solve my issue as each time I follow their advice of dispatching the 'change' event, nothing happens. Although, that was tested by dispatching the event on the body element since it's difficult to pin point the exact element that needs to be updated. So my current solution is trying to call StateHasChanged in hopes I can get Blazor to see the changes to the field inputs.
Other info I found:
Checked here, but they don't show calling an instanced method, they just mention it's possible but not how.
Second, I checked here, but I'd prefer not to pass around an instance of a component, just to call StateHasChanged.
Maybe I don't absolutely need to call StateHasChanged and I'm just dispatching the 'change' event improperly but there's no good examples of dispatching that event to Blazor anyway so maybe that's an even better solution.
Additional solution I've tried.
Edit 1:
I have now managed to call StateHasChanged, mind you not the way I would like it to be called but I called it, and it made no difference, Blazor still doesn't recognize the changed inputs. Guess I'll be trying the 'change' event stuff.
code:
//button in Blazor component:
<button type="button" u/onclick='async (e) => await jsRuntime.InvokeAsync<Task>("ChangeValueFromJs", DotNetObjectReference.Create(this))'>Test</button>
//code in component:
[JSInvokable("invokeFromJS")]
public Task ChangeValue()
{
StateHasChanged();
return Task.CompletedTask;
}
//Javascript on client side page:
function ChangeValueFromJs(wrapper) {
return wrapper.invokeMethodAsync("invokeFromJS")
.then(_ => {
console.log('state has changed');
});
}
Edit 2 (Solution):
So I ended up going the JS route dispatching the 'change' event as a solution from SteveSandersonMS on an issue someone made on the Blazor repo very similar to mine. I did however learn two things that are very important for using this solution.
The event target for this dispatchEvent
(element.dispatchEvent('change', { 'bubbles' : true })), element in
this case, must be the input field, received from a querySelector
(let element = document.querySelector("#input-field-username"))
Bubbling should be true, although I haven't tested this, I think
someone mentioned it in one of my referenced pages that it is
important.
// Not the greatest but - submits an update for *all* input fields, not only the changed ones, maybe improve this later.
let elements = document.querySelectorAll(".address-form-input");
if (elements)
elements.forEach(p => p.dispatchEvent(new Event('change', { 'bubbles': true })))
Hopefully this helps anyone out there, cheers.
I am trying to write a custom rule (code analysis) where, if the body of a method contains empty statements, an error is raised.
However, there is one problem. I can not seem to figure out how to get the body of a method (the text that is in the method).
How can I get the text inside a method, and assign it to a string?
Thanks in advance.
For reference; I use c# in visual studio, with FxCop to make the rule.
Edit: Some code added for reference, this does NOT work.
using Microsoft.FxCop.Sdk;
using Microsoft.VisualStudio.CodeAnalysis.Extensibility;
public override ProblemCollection Check(Member member)
{
Method method = member as Method;
if (method == null)
{
return null;
}
if (method.Name.Name.Contains("{}"))
{
var resolution = GetResolution(member.Name.Name);
var problem = new Problem(resolution, method)
{
Certainty = 100,
FixCategory = FixCategories.Breaking,
MessageLevel = MessageLevel.Warning
};
Problems.Add(problem);
}
return Problems;
}
FxCop doesn't analyse source code, it works on .Net assemblies built from any language.
You may be able to find whether the method contains a statement or not using FxCop, I advice you to read the documentation and check the implementation of existing rules to understand it.
An empty statement in the middle of other code might be removed by the compiler and you may not find it using FxCop. If you want to analyze source code you should take a look at StyleCop.
However, there is one problem. I can not seem to figure out how to get the body of a method
(the text that is in the method).
You can not. FxCop does not work based on the source, but analysis the compiled bytecode.
What you can do is find the source - which is not totally trivial - but you have to do so without the FxCop API. A start point may be analysing the pdb files (not sure where to find documentation) as they can point you to the file that contains the method.
I'm trying to:
Parallel.ForEach(listOfNames, name => DoSometingWithName(name));
while VS asks me to convert method to group, while i can't since this method is used from other places as well. So i don't want to copy paste the code around.
Is there a way to ?
Caused by ReSharper thus guys without it never seen this message. I thought it was compiler error.
Elegant work around would be:
Parallel.ForEach(listOfNames, DoSometingWithName);
Not sure it is more readable though.
Not sure what you mean, but did you search this syntax?
Parallel.ForEach(listOfNames, name =>
{
//Place your code here.
DoSometingWithName(name);
});
This is maddening. I am trying to write a simple test using Moq (at the moment but I will use anything that works) that will verify that registerViewWithRegion was called but every freaking method in prism is a static extension method! I have searched the web looking for an example of this and haven't found anything... Hopefully someone can tell me how to go about this. Here is what I am trying to do.
var container = new UnityContainer();
var regionManagerMock = new Mock<IRegionManager>();
regionManagerMock.Setup(r => r.RegisterViewWithRegion("", typeof(RibbonControlView)));
container.RegisterInstance(regionManagerMock.Object);
RibbonControlModule ribbonControlModule = new RibbonControlModule(container);
ribbonControlModule.Initialize();
regionManagerMock.Verify(x => x.RegisterViewWithRegion("RibbonRegion", typeof(RibbonControlView)));
Of course that blows up cause RegisterViewWithRegion is a static extension method, every wanna be coding rockstar has written a howto about using tests but I can't find turd about about what to do when you run into something like this (static extension methods), I can't believe it's this hard... Or maybe I am just an idiot - that would be fine if someone could just explain how I go about doing this...
Just as a side note - I found this http://compositewpf.codeplex.com/discussions/68353?ProjectName=compositewpf - In that post they are using Rhino which I would use if it would work but it blows up as well... I don't know how that code in that post ever worked.
Thanks for any help!
You can get an instance of the IRegionViewRegistry instead of IRegionManager. As the RegisterViewWithRegion method, which is used to perform View Discovery, is an instance member, you will be able to mock it as desired.
I hope this helps.
Damian