I wanted to check if we can create a function name from variable value in C#. Here is what I am trying. I have a list of strings as below:
private List<string> _pages;
_pages.AddRange(new string[] { "Page1", "Page2", "Page3", "Page4"});
And I have tasks like below:
private async void Sync_Page1() {}
private async void Sync_Page2() {}
private async void Sync_Page3() {}
private async void Sync_Page4() {}
For each of those strings in the list, I need to call a method like below
foreach (string pageName in _pages)
{
Task.Run(async () => { Sync_pageName() }); // where pageName will be the items from list.
}
Tried searching on google but didn't find anything specific. So not sure if that can be done in C# but was wondering if there is a possibility.
Any thoughts?
You can map it to dictionary items which you can invoke :
namespace ConsoleApp1
{
class Program
{
public static void Main(String[] args)
{
PagesExecution pe = new PagesExecution();
pe.Execute();
Console.ReadLine();
}
}
public class PagesExecution
{
//Action<string> a = new Action<string>();
private List<string> _pages = new List<string>();
private Dictionary<string, Action> dictionary = new Dictionary<string, Action>();
public PagesExecution ()
{
}
public void Execute()
{
dictionary.Add("Page1", new Action(Sync_Page1));
dictionary.Add("Page2", Sync_Page2);
dictionary.Add("Page3", Sync_Page3);
dictionary.Add("Page4", Sync_Page4);
_pages.AddRange(new string[] { "Page1", "Page2", "Page3", "Page4"});
foreach (var entry in _pages)
{
dictionary[entry].Invoke();
}
}
public void Sync_Page1()
{
Console.WriteLine("Page1");
}
private void Sync_Page2()
{
Console.WriteLine("Page2");
}
private void Sync_Page3()
{
Console.WriteLine("Page3");
}
private void Sync_Page4()
{
Console.WriteLine("Page4");
}
}
}
Related
Hello everyone i am getting the messages of the users in android studio for that i am refreshing the recyclerview every second but the probem is scrolling when i am scrooling the recyclerview to old messages then its not scrooling becouse of the getting data every second can someone please help me in this
bellow is my activity code
public class Message_User_Activity extends AppCompatActivity {
private RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message_user);
content();
Clicks();
}
public void content()
{
getdata();
refresh(100);
}
private void refresh(int milliseconds)
{
final Handler handler = new Handler();
final Runnable runnable = new Runnable() {
#Override
public void run() {
content();
}
};
handler.postDelayed(runnable,milliseconds);
}
private void getdata()
{
toolbar_user_name.setText(name);
String Choice = "Get Messages";
Call<List<responsemodel>> call = SplashScreen.apiInterface.getfullprofiledata(Choice,Message_To,Message_From);
call.enqueue(new Callback<List<responsemodel>>() {
#Override
public void onResponse(Call<List<responsemodel>> call, Response<List<responsemodel>> response) {
List<responsemodel> data = response.body();
Message_user_Adapter adapter = new Message_user_Adapter(data,Message_To);
messages_Message_user_RecyclerView.setAdapter(adapter);
messages_Message_user_RecyclerView.scrollToPosition(messages_Message_user_RecyclerView.getAdapter().getItemCount() -1);
}
#Override
public void onFailure(Call<List<responsemodel>> call, Throwable t) {
}
});
}
}
below is my adapter code
public class Message_user_Adapter extends RecyclerView.Adapter<Message_user_Adapter.Message_user_Adapter_View_Holder>
{
List<responsemodel> data;
String mmessage_To;
public Message_user_Adapter(List<responsemodel> data, String message_To) {
this.data = data;
this.mmessage_To = message_To;
}
#NonNull
#Override
public Message_user_Adapter_View_Holder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.user_messages_layout,parent,false);
return new Message_user_Adapter_View_Holder(view);
}
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onBindViewHolder(#NonNull Message_user_Adapter_View_Holder holder, int position) {
String time = calculateTime(data.get(position).getMessage_Time());
if (data.get(position).getMessage_From().equals(mmessage_To))
{
holder.other_user_message_message_layout.setVisibility(View.VISIBLE);
holder.other_user_message_message_layout.setText(data.get(position).getMessage() + "\n \n" + time);
holder.message_message_layout.setVisibility(View.GONE);
}
else
{
holder.other_user_message_message_layout.setVisibility(View.GONE);
holder.message_message_layout.setText(data.get(position).getMessage() + "\n \n" + time);
holder.message_message_layout.setVisibility(View.VISIBLE);
}
}
#RequiresApi(api = Build.VERSION_CODES.N)
private String calculateTime(String post_time)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
try {
long time = sdf.parse(post_time).getTime();
long now = System.currentTimeMillis();
CharSequence ago =
DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
return ago+"";
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
#Override
public int getItemCount() {
return data.size();
}
public String getdata() {
return mmessage_To.toString();
}
class Message_user_Adapter_View_Holder extends RecyclerView.ViewHolder
{
TextView other_user_message_message_layout;
TextView message_message_layout;
CircleImageView toolbar_user_profile;
public Message_user_Adapter_View_Holder(#NonNull View itemView) {
super(itemView);
other_user_message_message_layout = itemView.findViewById(R.id.other_user_message_message_layout);
message_message_layout = itemView.findViewById(R.id.message_message_layout);
}
}
}
According to my simple information
in your getdata() function. you send new data to Message_user_Adapter of RecyclerView every time you receive data from API or whatever you use ,so the data of adapter every second is change to new data ,so the RecyclerView being recreated every second with new data and the scroll will not work
just try to outage this lines from onResponse to the first of getdata():
Message_user_Adapter adapter = new Message_user_Adapter(data,Message_To);
messages_Message_user_RecyclerView.setAdapter(adapter);
and in its place add this line to notify the adapter about changed data :
adapter.notifyDatasetChanged()
something like this :
private void getdata() {
toolbar_user_name.setText(name);
String Choice = "Get Messages";
List<responsemodel> data = new ArrayList<>();//this line was change
Message_user_Adapter adapter = new Message_user_Adapter(data,Message_To);//this line was change
messages_Message_user_RecyclerView.setAdapter(adapter);//this line was change
Call<List<responsemodel>> call = SplashScreen.apiInterface.getfullprofiledata(Choice,Message_To,Message_From);
call.enqueue(new Callback<List<responsemodel>>() {
#Override
public void onResponse(Call<List<responsemodel>> call, Response<List<responsemodel>> response) {
data = response.body();
adapter.notifyDatasetChanged()//this line was added
messages_Message_user_RecyclerView.scrollToPosition(messages_Message_user_RecyclerView.getAdapter().getItemCount() -1);
}
#Override
public void onFailure(Call<List<responsemodel>> call, Throwable t) {
}
});
}
I have a json that looks like this:
[
{
_id: "54b8f62fa08c286b08449b8f",
loc: [
36.860983,
31.0567
]
},
{
_id: "54b8f6aea08c286b08449b93",
loc: {
coordinates: [ ]
}
}
]
As you can see, loc object is sometimes is a json object, sometimes is a double array. Without writing a custom deserializer, is there a way to avoid JsonSyntaxException and set the loc object to null when it is a json object rather than a double array.
There aren't any easy way (I mean a property/method call at Gson) for custom seralization/deserialization of a specific field at a json value.
You can see source code of com.google.gson.internal.bind.ReflectiveTypeAdapterFactory, and debug on its inner class Adapter's read method. (That's where your JsonSyntaxException occurs)
You can read Custom serialization for JUST specific fields and track its links. It may be implemented at future release of Gson. (Not available at latest release 2.2.4)
I would write some code for this. Maybe that's not what you are looking for but it may help somebody else.)
Solution 1 (This has less code compared with the second solution but second solution's performance is much more better):
public class SubClass extends BaseClass {
private double[] loc;
}
public class BaseClass {
#SerializedName("_id")
private String id;
}
public class CustomTypeAdapter extends TypeAdapter<BaseClass> {
private Gson gson;
public CustomTypeAdapter() {
this.gson = new Gson();
}
#Override
public void write(JsonWriter out, BaseClass value)
throws IOException {
throw new RuntimeException("Not implemented for this question!");
}
#Override
public BaseClass read(JsonReader in) throws IOException {
BaseClass instance;
try {
instance = gson.fromJson(in, SubClass.class);
} catch (Exception e) {
e.printStackTrace();
instance = gson.fromJson(in, BaseClass.class);
}
return instance;
}
}
Test:
private void test() {
String json = "[{_id:\"54b8f62fa08c286b08449b8f\",loc:[36.860983,31.0567]},{_id:\"54b8f6aea08c286b08449b93\",loc:{coordinates:[]}}]";
Type collectionType = new TypeToken<List<BaseClass>>(){}.getType();
Gson gson = new GsonBuilder().registerTypeAdapter(BaseClass.class, new CustomTypeAdapter()).create();
List<BaseClass> list = gson.fromJson(json, collectionType);
for(BaseClass item : list) {
if(item instanceof SubClass) {
System.out.println("item has loc value");
SubClass subClassInstance = (SubClass)item;
} else {
System.out.println("item has no loc value");
BaseClass baseClassInstance = item;
}
}
}
Solution 2 (It is one of the Gson Developers suggestion. See original post.):
Copy below class to your project. It is going to be a base class for your custom TypeAdapterFactorys.
public abstract class CustomizedTypeAdapterFactory<C>
implements TypeAdapterFactory {
private final Class<C> customizedClass;
public CustomizedTypeAdapterFactory(Class<C> customizedClass) {
this.customizedClass = customizedClass;
}
#SuppressWarnings("unchecked") // we use a runtime check to guarantee that 'C' and 'T' are equal
public final <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
return type.getRawType() == customizedClass
? (TypeAdapter<T>) customizeMyClassAdapter(gson, (TypeToken<C>) type)
: null;
}
private TypeAdapter<C> customizeMyClassAdapter(Gson gson, TypeToken<C> type) {
final TypeAdapter<C> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
return new TypeAdapter<C>() {
#Override public void write(JsonWriter out, C value) throws IOException {
JsonElement tree = delegate.toJsonTree(value);
beforeWrite(value, tree);
elementAdapter.write(out, tree);
}
#Override public C read(JsonReader in) throws IOException {
JsonElement tree = elementAdapter.read(in);
afterRead(tree);
return delegate.fromJsonTree(tree);
}
};
}
/**
* Override this to muck with {#code toSerialize} before it is written to
* the outgoing JSON stream.
*/
protected void beforeWrite(C source, JsonElement toSerialize) {
}
/**
* Override this to muck with {#code deserialized} before it parsed into
* the application type.
*/
protected void afterRead(JsonElement deserialized) {
}
}
Write your POJO and your custom CustomizedTypeAdapterFactory. Override afterRead method and handle double array as you asked at your question:
public class MyClass {
#SerializedName("_id")
private String id;
private double[] loc;
// getters/setters
}
private class MyClassTypeAdapterFactory extends CustomizedTypeAdapterFactory<MyClass> {
private MyClassTypeAdapterFactory() {
super(MyClass.class);
}
#Override protected void afterRead(JsonElement deserialized) {
try {
JsonArray jsonArray = deserialized.getAsJsonObject().get("loc").getAsJsonArray();
System.out.println("loc is not a double array, its ignored!");
} catch (Exception e) {
deserialized.getAsJsonObject().remove("loc");
}
}
}
Test:
private void test() {
String json = "[{_id:\"54b8f62fa08c286b08449b8f\",loc:[36.860983,31.0567]},{_id:\"54b8f6aea08c286b08449b93\",loc:{coordinates:[]}}]";
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new MyClassTypeAdapterFactory())
.create();
Type collectionType = new TypeToken<List<MyClass>>(){}.getType();
List<MyClass> list = gson.fromJson(json, collectionType);
for(MyClass item : list) {
if(item.getLoc() != null) {
System.out.println("item has loc value");
} else {
System.out.println("item has no loc value");
}
}
}
This is how I did this. It is shorter, but I think #DevrimTuncers answer is the best one.
//This is just Double array to use as location object
public class Location extends ArrayList<Double> {
public Double getLatidute() {
if (this.size() > 0) {
return this.get(0);
} else {
return (double) 0;
}
}
public Double getLongitude() {
if (this.size() > 1) {
return this.get(1);
} else {
return (double) 0;
}
}
public static class LocationDeserializer implements JsonDeserializer<Location> {
#Override
public Location deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
try {
JsonArray array = json.getAsJsonArray();
Location location = new Location();
for (int i = 0; i < array.size(); i++) {
location.add(array.get(i).getAsDouble());
}
return location;
} catch (Exception e) {
return null;
}
}
}
}
GSON Throwing Syntax exception While parsing the JSON into a Java Objects. Here I have attached my JSON and the Classes by which JSON has been parsed and the code where I am parsing the JSON values. Please help me to fix this error.
The following is my JSON Response Which is to be parsed.
JSON
[
{ "counter":1,
"data":{
"b":[
{"d":11.080666011022274,"e":-9.84375},
{"d":21.36033117555945,"e":-13.18359375},
{"d":25.55169302685644,"e":-5.09765625},
{"d":20.209969075006228,"e":24.9609375},
{"d":6.740259027196141,"e":27.7734375},
{"d":19.38301389529031,"e":10.01953125}
],
"gm_accessors_":{"length":null},
"length":6,
"gm_bindings_":{"length":{}}
}
},
{ "counter":2,
"data":{
"b":[
{"d":43.76263306667474,"e":60.1171875},
{"d":56.310038487065135,"e":47.8125},
{"d":60.881999484084055,"e":78.22265625},
{"d":55.81939178481952,"e":96.6796875},
{"d":44.76961886697326,"e":99.84375},
{"d":55.72051189919337,"e":82.08984375},
{"d":40.50489156437503,"e":81.5625},
{"d":52.74250152629922,"e":72.0703125}
],
"gm_accessors_":{"length":null},
"length":8,
"gm_bindings_":{"length":{}}
}
}
]
The Above Json has been parsed by the following JAVA classes. In the following Class structure I am making Mistake. Please guide me where I am doing the mistake.
**Parent Class -- SHAPE**
public class Shape {
#SerializedName("counter")
private Integer mCounter;
#SerializedName("data")
private Data mData;
public Data getmData() {
return mData;
}
public void setmData(Data mData) {
this.mData = mData;
}
public Integer getCounter() {
return mCounter;
}
public void setCounter(Integer counter) {
this.mCounter = counter;
}
}
**CHILD CLASS -- DATA**
public class Data {
#SerializedName("length")
private Integer length;
#SerializedName("b")
private b mCoordinates;
public Integer getLength() {
return length;
}
public void setLength(Integer length) {
this.length = length;
}
public b getmCoordinates() {
return mCoordinates;
}
public void setmCoordinates(b mCoordinates) {
this.mCoordinates = mCoordinates;
}
}
**GRAND CHILD CLASS -- b**
public class b {
#SerializedName("d")
private ArrayList<Float> lattitude;
#SerializedName("e")
private ArrayList<Float> longtitude;
public ArrayList<Float> getLattitude() {
return lattitude;
}
public void setLattitude(ArrayList<Float> lattitude) {
this.lattitude = lattitude;
}
public ArrayList<Float> getLongtitude() {
return longtitude;
}
public void setLongtitude(ArrayList<Float> longtitude) {
this.longtitude = longtitude;
}
}
JSON PARSING -- CHANGING JSON AS A JAVA OBJECTS
JsonParser parser = new JsonParser();
JsonArray jArray = parser.parse(jsonContent).getAsJsonArray();
System.out.println("Array :_: " + jArray);
for(JsonElement jsonElement : jArray) {
System.out.println("JSON_ELEMENT :_: " + jsonElement);
Shape shape = gson.fromJson(jsonElement, Shape.class);
System.out.println("Counter :_: " + shape.getCounter());
}
Please chnage your data class to :
public class Data {
#SerializedName("length")
private Integer length;
#SerializedName("b")
// this is where the error was thrown,
// it was expecting an array but only received a single object.
private List<b> mCoordinates;
public Integer getLength() {
return length;
}
public void setLength(Integer length) {
this.length = length;
}
public List<b> getmCoordinates() {
return mCoordinates;
}
public void setmCoordinates(List<b> mCoordinates) {
this.mCoordinates = mCoordinates;
}
}
And also change the b class to:
public class b {
#SerializedName("d")
private double d;
#SerializedName("e")
private double e;
public double getD() {
return d;
}
public void setD(double d) {
this.d = d;
}
public double getE() {
return e;
}
public void setE(double e) {
this.e = e;
}
}
use:
Gson gson = new Gson();
Shape shape = gson.fromJson(reader/string here, Shape.class);
and your shape class will be filled.
public class Shape {
#SerializedName("counter")
private Integer mCounter;
#SerializedName("data")
private Data mData;
// geter/setter here
}
public class Data {
#SerializedName("length")
private Integer length;
#SerializedName("b")
private List<Coordinate> coordinates;
#SerializedName("gm_accessors_")
private Accessors gmAccessors;
//getter setter here
}
public class Coordinate {
private float d;
private float e;
}
public class Accessors {
private Integer length;
}
Finally Parse it as
Shape[] shapes = gson.fromJson(jArray, Shape[].class);
If you will parse like this you will get same error : Expected BEGIN_OBJECT but was BEGIN_ARRAY
Shape shape = gson.fromJson(jArray, Shape.class);
I have some JSON where one of the keys has one of three values: an int, a string, or a json object. Using the snippet below I can map this field when it is an int or a string but fail when it's a json object. Where am I going wrong? What should I be doing?
The JSON value key looks like:
"value": 51,
or
"value": 51,
or (and this is where I am having trouble)
"value": {"lat": 53.990614999999998, "lng": -1.5391117000000301, "addr": "Harrogate, North Yorkshire, UK"}
public class Test {
public Test() {
}
public static class Value {
public int slidervalue;
public String voicevalue;
public GeoValue geovalue; // problem
public Value(int value) {
this.slidervalue = value
}
public Value(String value) {
this.voicevalue = value;
}
public Value(JSONObject value) {
JSONObject foo = value; // this is never reached
this.geovalue = value; // and how would this work so as map value to a GeoValue?
}
private static class GeoValue {
private double _lat;
private double _lng;
private String _addr;
public float getLat() {
return (float)_lat;
}
public void setLat(float lat) {
_lat = (double)lat;
}
public float getLng() { return (float)_lng;}
public void setLng(float lng) { _lng = (double)lng; }
public String getAddr() { return _addr;}
public void setAddr(String addr) { _addr = addr; }
}
} // end of Value class
public Value getValue() { return _value;}
public void setValue(Value value) {
_value = value;
}
} //end of Test class
and this is being used like this:
ObjectMapper mapper = new ObjectMapper();
instance = mInstances.getJSONObject(i).toString();
Test testinstance = mapper.readValue(instance, Test.class);
public class Test {
public Test() {
}
public static class Value {
public int slidervalue;
public String voicevalue;
public GeoValue geovalue; // problem
public Value(int value) {
this.slidervalue = value
}
public Value(String value) {
this.voicevalue = value;
}
public Value(JSONObject value) {
JSONObject foo = value; // this is never reached
this.geovalue = value; // and how would this work so as map value to a GeoValue?
}
private static class GeoValue {
private double _lat;
private double _lng;
private String _addr;
public float getLat() {
return (float)_lat;
}
public void setLat(float lat) {
_lat = (double)lat;
}
public float getLng() { return (float)_lng;}
public void setLng(float lng) { _lng = (double)lng; }
public String getAddr() { return _addr;}
public void setAddr(String addr) { _addr = addr; }
}
} // end of Value class
public Value getValue() { return _value;}
public void setValue(Value value) {
_value = value;
}
} //end of Test class
and this is being used like this:
ObjectMapper mapper = new ObjectMapper();
instance = mInstances.getJSONObject(i).toString();
Test testinstance = mapper.readValue(instance, Test.class);
This fails with a JSONMappingException: No suitable contructor found for type ... 'value'
Thanks. Alex
What might work is that you mark the constructor that takes JSONObject with #JsonCreator, but do NOT add #JsonProperty for the single parameter. In that case, incoming JSON is bound to type of that parameter (in this case JSONObject, but you could use Map as well), and passed to constructor.
Overloading still works because of special handling for single-string/int/long-argument constructor.
I am not sure if that is the cleanest solution; it might be cleanest to just implement custom deserializer. But it should work.
If your code is what you want, your json should be like this:
{"value":{"slidervalue":1,"voicevalue":"aa","geovalue":{"lat":53.990615,"lng":-1.53911170000003,"addr":"Harrogate, North Yorkshire, UK"}}}
I run this at the application Start Up
public class ConfigurationFacility : AbstractFacility {
private readonly List<string> configuredComponents = new List<string>();
protected override void Init() {
Kernel.ComponentRegistered += OnComponentRegistered;
// add environment configurators
}
private void OnComponentRegistered(string key, IHandler handler) {
// if the component is a configurator then run conf settings and add it to configuredComponents
}}
Question: How to hook tear down and to call explicit release for each ?
Thanks
You can use either the ComponentDestroyed event of IKernel or just implement IDisposable in your components. Here's a little sample code:
namespace WindsorInitConfig {
[TestFixture]
public class ConfigurationFacilityTests {
[Test]
public void tt() {
OneDisposableComponent component = null;
using (var container = new WindsorContainer()) {
container.AddFacility<ConfigurationFacility>();
container.AddComponent<OneDisposableComponent>();
component = container.Resolve<OneDisposableComponent>();
}
Assert.IsTrue(component.Disposed);
Assert.Contains(component, ConfigurationFacility.DestroyedComponents);
}
public class OneDisposableComponent : IDisposable {
public bool Disposed { get; private set; }
public void Dispose() {
Disposed = true;
}
}
public class ConfigurationFacility : AbstractFacility {
private readonly List<string> configuredComponents = new List<string>();
public static readonly ArrayList DestroyedComponents = new ArrayList();
protected override void Init() {
Kernel.ComponentRegistered += OnComponentRegistered;
Kernel.ComponentDestroyed += Kernel_ComponentDestroyed;
// add environment configurators
}
private void Kernel_ComponentDestroyed(ComponentModel model, object instance) {
DestroyedComponents.Add(instance);
// uninitialization, cleanup
}
private void OnComponentRegistered(string key, IHandler handler) {
// if the component is a configurator then run conf settings and add it to configuredComponents
configuredComponents.Add(key);}
}
}
}
The static ArrayList is only for demo purposes, of course.